From a8afc9940187a7187da1b003a4879ef4505c6f03 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 14 May 2022 17:41:35 +0200 Subject: [PATCH] Art timelines --- .../app/fedilab/android/BaseMainActivity.java | 2 - .../android/client/entities/Timeline.java | 2 + .../client/mastodon/entities/Status.java | 12 +- .../android/helper/PinnedTimelineHelper.java | 106 ++++++++++-------- .../android/helper/SpannableHelper.java | 4 +- .../android/ui/drawer/StatusAdapter.java | 103 +++++++++++++---- .../timeline/FragmentMastodonTimeline.java | 42 ++++++- .../ui/pageadapter/FedilabPageAdapter.java | 3 +- app/src/main/res/layout/drawer_status_art.xml | 91 +++++++++++++++ 9 files changed, 289 insertions(+), 76 deletions(-) create mode 100644 app/src/main/res/layout/drawer_status_art.xml diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java index 97d233fcf..512266dc7 100644 --- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java @@ -73,7 +73,6 @@ import com.jaredrummler.cyanea.Cyanea; import java.io.File; import java.lang.ref.WeakReference; -import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; @@ -122,7 +121,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt public static Account.API api; public static boolean admin; public static WeakReference accountWeakReference; - public static HashMap mPageReferenceMap; public static status networkAvailable = UNKNOWN; public static Instance instanceInfo; public static List mainFilters; diff --git a/app/src/main/java/app/fedilab/android/client/entities/Timeline.java b/app/src/main/java/app/fedilab/android/client/entities/Timeline.java index 35b0eaa2f..dd40eff7d 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/Timeline.java +++ b/app/src/main/java/app/fedilab/android/client/entities/Timeline.java @@ -364,6 +364,8 @@ public class Timeline { PUBLIC("PUBLIC"), @SerializedName("TAG") TAG("TAG"), + @SerializedName("ART") + ART("ART"), @SerializedName("LIST") LIST("LIST"), @SerializedName("REMOTE") diff --git a/app/src/main/java/app/fedilab/android/client/mastodon/entities/Status.java b/app/src/main/java/app/fedilab/android/client/mastodon/entities/Status.java index 702c6e959..199f0711a 100644 --- a/app/src/main/java/app/fedilab/android/client/mastodon/entities/Status.java +++ b/app/src/main/java/app/fedilab/android/client/mastodon/entities/Status.java @@ -16,13 +16,15 @@ package app.fedilab.android.client.mastodon.entities; import android.text.Spannable; +import androidx.annotation.NonNull; + import com.google.gson.annotations.SerializedName; import java.io.Serializable; import java.util.Date; import java.util.List; -public class Status implements Serializable { +public class Status implements Serializable, Cloneable { @SerializedName("id") public String id; @@ -83,6 +85,9 @@ public class Status implements Serializable { @SerializedName("poll") public Poll poll; + + public Attachment art_attachment; + //Some extra spannable element - They will be filled automatically when fetching the status public transient Spannable span_content; public transient Spannable span_spoiler_text; @@ -98,4 +103,9 @@ public class Status implements Serializable { public transient boolean setCursorToEnd = false; public transient int cursorPosition = 0; + @NonNull + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } diff --git a/app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java b/app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java index 35be2f1ce..9a6f9bff5 100644 --- a/app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java @@ -14,7 +14,6 @@ package app.fedilab.android.helper; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ -import static app.fedilab.android.BaseMainActivity.mPageReferenceMap; import static app.fedilab.android.ui.pageadapter.FedilabPageAdapter.BOTTOM_TIMELINE_COUNT; import android.content.Context; @@ -192,10 +191,10 @@ public class PinnedTimelineHelper { break; case TAG: - tagClick(activity, finalPinned, v, finalI); + tagClick(activity, finalPinned, v, activityMainBinding, finalI); break; case REMOTE: - instanceClick(activity, finalPinned, v, finalI); + instanceClick(activity, finalPinned, v, activityMainBinding, finalI); break; } return true; @@ -265,7 +264,7 @@ public class PinnedTimelineHelper { * @param view - View * @param position - int position of the tab */ - public static void tagClick(Context context, Pinned pinned, View view, int position) { + public static void tagClick(Context context, Pinned pinned, View view, ActivityMainBinding activityMainBinding, int position) { PopupMenu popup = new PopupMenu(new ContextThemeWrapper(context, Helper.popupStyle()), view); int offSetPosition = position - BOTTOM_TIMELINE_COUNT; @@ -295,24 +294,23 @@ public class PinnedTimelineHelper { itemShowNSFW.setChecked(showNSFW[0]); popup.setOnDismissListener(menu1 -> { if (changes[0]) { - if (mPageReferenceMap == null) - return; - FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); - FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position); - if (fragmentMastodonTimeline == null) - return; - fragTransaction.detach(fragmentMastodonTimeline); - Bundle bundle = new Bundle(); - bundle.putString("tag", tagTimeline.name); - bundle.putInt("timelineId", tagTimeline.id); - bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG); - if (mediaOnly[0]) - bundle.putString("instanceType", "ART"); - else - bundle.putString("instanceType", "MASTODON"); - fragmentMastodonTimeline.setArguments(bundle); - fragTransaction.attach(fragmentMastodonTimeline); - fragTransaction.commit(); + FragmentMastodonTimeline fragmentMastodonTimeline; + if (activityMainBinding.viewPager.getAdapter() != null) { + Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition()); + if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) { + fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment); + FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); + fragTransaction.detach(fragmentMastodonTimeline).commit(); + Bundle bundle = new Bundle(); + bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG); + bundle.putSerializable(Helper.ARG_TAG_TIMELINE, tagTimeline); + fragmentMastodonTimeline.setArguments(bundle); + FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); + fragTransaction2.attach(fragmentMastodonTimeline); + fragTransaction2.commit(); + } + } + } }); @@ -479,7 +477,7 @@ public class PinnedTimelineHelper { * @param view - View * @param position - int position of the tab */ - public static void instanceClick(Context context, Pinned pinned, View view, int position) { + public static void instanceClick(Context context, Pinned pinned, View view, ActivityMainBinding activityMainBinding, int position) { PopupMenu popup = new PopupMenu(new ContextThemeWrapper(context, Helper.popupStyle()), view); int offSetPosition = position - BOTTOM_TIMELINE_COUNT; @@ -512,12 +510,17 @@ public class PinnedTimelineHelper { } }); changes[0] = true; - FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); - if (mPageReferenceMap == null) - return true; - FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position); + FragmentMastodonTimeline fragmentMastodonTimeline = null; + if (activityMainBinding.viewPager.getAdapter() != null) { + Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition()); + if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) { + fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment); + } + } if (fragmentMastodonTimeline == null) return false; + FragmentTransaction fragTransaction1 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); + pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = null; remoteInstance.filteredWith = null; currentFilter[0] = null; @@ -527,15 +530,16 @@ public class PinnedTimelineHelper { } catch (DBException e) { e.printStackTrace(); } - fragTransaction.detach(fragmentMastodonTimeline); + fragTransaction1.detach(fragmentMastodonTimeline).commit(); Bundle bundle = new Bundle(); bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : ""); bundle.putString("instanceType", remoteInstance.type.getValue()); bundle.putString("timelineId", remoteInstance.id); bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE); fragmentMastodonTimeline.setArguments(bundle); - fragTransaction.attach(fragmentMastodonTimeline); - fragTransaction.commit(); + FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); + fragTransaction2.attach(fragmentMastodonTimeline); + fragTransaction2.commit(); popup.getMenu().close(); return false; }); @@ -553,10 +557,15 @@ public class PinnedTimelineHelper { } MenuItem item = popup.getMenu().add(0, 0, Menu.NONE, title); item.setOnMenuItemClickListener(item1 -> { - FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); - if (mPageReferenceMap == null) - return true; - FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position); + FragmentMastodonTimeline fragmentMastodonTimeline = null; + if (activityMainBinding.viewPager.getAdapter() != null) { + Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition()); + if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) { + fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment); + fragmentMastodonTimeline.refreshAllAdapters(); + } + } + FragmentTransaction fragTransaction1 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); if (fragmentMastodonTimeline == null) return false; pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = tag; @@ -567,7 +576,7 @@ public class PinnedTimelineHelper { e.printStackTrace(); } currentFilter[0] = remoteInstance.filteredWith; - fragTransaction.detach(fragmentMastodonTimeline); + fragTransaction1.detach(fragmentMastodonTimeline).commit(); Bundle bundle = new Bundle(); bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : ""); bundle.putString("instanceType", remoteInstance.type.getValue()); @@ -575,8 +584,9 @@ public class PinnedTimelineHelper { bundle.putString("currentfilter", remoteInstance.filteredWith); bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE); fragmentMastodonTimeline.setArguments(bundle); - fragTransaction.attach(fragmentMastodonTimeline); - fragTransaction.commit(); + FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); + fragTransaction2.attach(fragmentMastodonTimeline); + fragTransaction2.commit(); return false; }); } @@ -621,7 +631,7 @@ public class PinnedTimelineHelper { } popup.getMenu().clear(); popup.getMenu().close(); - instanceClick(context, pinned, view, position); + instanceClick(context, pinned, view, activityMainBinding, position); }); AlertDialog alertDialog = dialogBuilder.create(); alertDialog.show(); @@ -630,13 +640,18 @@ public class PinnedTimelineHelper { popup.setOnDismissListener(menu -> { if (changes[0]) { - FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); - if (mPageReferenceMap == null) - return; - FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position); + FragmentMastodonTimeline fragmentMastodonTimeline = null; + if (activityMainBinding.viewPager.getAdapter() != null) { + Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition()); + if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) { + fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment); + fragmentMastodonTimeline.refreshAllAdapters(); + } + } + FragmentTransaction fragTransaction1 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); if (fragmentMastodonTimeline == null) return; - fragTransaction.detach(fragmentMastodonTimeline); + fragTransaction1.detach(fragmentMastodonTimeline).commit(); Bundle bundle = new Bundle(); bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : ""); bundle.putString("instanceType", remoteInstance.type.getValue()); @@ -646,8 +661,9 @@ public class PinnedTimelineHelper { } bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE); fragmentMastodonTimeline.setArguments(bundle); - fragTransaction.attach(fragmentMastodonTimeline); - fragTransaction.commit(); + FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction(); + fragTransaction2.attach(fragmentMastodonTimeline); + fragTransaction2.commit(); } }); diff --git a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java index 412badb88..3b9621373 100644 --- a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java @@ -161,7 +161,9 @@ public class SpannableHelper { while (matcherALink.find()) { int matchStart = matcherALink.start() - offSetTruncate; int matchEnd = matchStart + matcherALink.group().length(); - + if (matchEnd > content.toString().length()) { + matchEnd = content.toString().length(); + } final String url = content.toString().substring(matchStart, matchEnd); String newURL = Helper.transformURL(context, url); //If URL has been transformed diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index 4d680bb01..d521aedc2 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -86,6 +86,7 @@ import com.varunest.sparkbutton.SparkButton; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import java.util.regex.Matcher; @@ -106,6 +107,7 @@ import app.fedilab.android.client.mastodon.entities.Attachment; import app.fedilab.android.client.mastodon.entities.Notification; import app.fedilab.android.client.mastodon.entities.Poll; import app.fedilab.android.client.mastodon.entities.Status; +import app.fedilab.android.databinding.DrawerStatusArtBinding; import app.fedilab.android.databinding.DrawerStatusBinding; import app.fedilab.android.databinding.DrawerStatusHiddenBinding; import app.fedilab.android.databinding.DrawerStatusNotificationBinding; @@ -131,6 +133,10 @@ public class StatusAdapter extends RecyclerView.Adapter private Context context; private final Timeline.TimeLineEnum timelineType; + public static final int STATUS_HIDDEN = 0; + public static final int STATUS_VISIBLE = 1; + public static final int STATUS_ART = 2; + public StatusAdapter(List statuses, Timeline.TimeLineEnum timelineType, boolean minified) { this.statusList = statuses; this.timelineType = timelineType; @@ -188,14 +194,13 @@ public class StatusAdapter extends RecyclerView.Adapter * Manage status, this method is also reused in notifications timelines * * @param context Context - * @param context Timeline.TimeLineEnum timelineType * @param statusesVM StatusesVM - For handling actions in background to the correct activity * @param searchVM SearchVM - For handling remote actions * @param holder StatusViewHolder * @param adapter RecyclerView.Adapter - General adapter that can be for {@link StatusAdapter} or {@link NotificationAdapter} * @param statusList List * @param notificationList List - * @param timelineType Timeline.TimeLineEnum + * @param timelineType Timeline.TimeLineEnum timelineTypeTimeline.TimeLineEnum * @param status {@link Status} */ @SuppressLint("ClickableViewAccessibility") @@ -1545,17 +1550,24 @@ public class StatusAdapter extends RecyclerView.Adapter @Override public int getItemViewType(int position) { - return isVisble(timelineType, statusList.get(position)) ? 1 : 0; + if (timelineType == Timeline.TimeLineEnum.ART) { + return STATUS_ART; + } else { + return isVisble(timelineType, statusList.get(position)) ? STATUS_VISIBLE : STATUS_HIDDEN; + } } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { context = parent.getContext(); - if (viewType == 0) { + if (viewType == STATUS_HIDDEN) { //Hidden statuses - ie: filtered DrawerStatusHiddenBinding itemBinding = DrawerStatusHiddenBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new StatusViewHolder(itemBinding); - } else { + } else if (viewType == STATUS_ART) { //Art statuses + DrawerStatusArtBinding itemBinding = DrawerStatusArtBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + return new StatusViewHolder(itemBinding); + } else { //Classic statuses if (!minified) { DrawerStatusBinding itemBinding = DrawerStatusBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new StatusViewHolder(itemBinding); @@ -1581,29 +1593,67 @@ public class StatusAdapter extends RecyclerView.Adapter @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { - if (viewHolder.getItemViewType() == 0) { + //Nothing to do with hidden statuses + if (viewHolder.getItemViewType() == STATUS_HIDDEN) { return; } Status status = statusList.get(position); - StatusViewHolder holder = (StatusViewHolder) viewHolder; - StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class); - SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class); - statusManagement(context, statusesVM, searchVM, holder, this, statusList, null, status, timelineType, minified); - if (holder.timer != null) { - holder.timer.cancel(); - holder.timer = null; - } - if (status.emojis != null && status.emojis.size() > 0) { - holder.timer = new Timer(); - holder.timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - Handler mainHandler = new Handler(Looper.getMainLooper()); - Runnable myRunnable = () -> holder.binding.statusContent.invalidate(); - mainHandler.post(myRunnable); + if (viewHolder.getItemViewType() == STATUS_VISIBLE) { + StatusViewHolder holder = (StatusViewHolder) viewHolder; + StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class); + SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class); + statusManagement(context, statusesVM, searchVM, holder, this, statusList, null, status, timelineType, minified); + if (holder.timer != null) { + holder.timer.cancel(); + holder.timer = null; + } + if (status.emojis != null && status.emojis.size() > 0) { + holder.timer = new Timer(); + holder.timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> holder.binding.statusContent.invalidate(); + mainHandler.post(myRunnable); - } - }, 100, 100); + } + }, 100, 100); + } + } else if (viewHolder.getItemViewType() == STATUS_ART) { + StatusViewHolder holder = (StatusViewHolder) viewHolder; + MastodonHelper.loadPPMastodon(holder.bindingArt.artPp, status.account); + Glide.with(holder.bindingArt.artMedia.getContext()) + .load(status.art_attachment.preview_url) + .apply(new RequestOptions().transform(new RoundedCorners((int) Helper.convertDpToPixel(3, context)))) + .into(holder.bindingArt.artMedia); + holder.bindingArt.artAcct.setText(status.account.span_display_name, TextView.BufferType.SPANNABLE); + holder.bindingArt.artUsername.setText(String.format(Locale.getDefault(), "@%s", status.account.acct)); + holder.bindingArt.artPp.setOnClickListener(v -> { + Intent intent = new Intent(context, ProfileActivity.class); + Bundle b = new Bundle(); + b.putSerializable(Helper.ARG_ACCOUNT, status.account); + intent.putExtras(b); + ActivityOptionsCompat options = ActivityOptionsCompat + .makeSceneTransitionAnimation((Activity) context, holder.bindingArt.artPp, context.getString(R.string.activity_porfile_pp)); + context.startActivity(intent, options.toBundle()); + }); + holder.bindingArt.artMedia.setOnClickListener(v -> { + Intent mediaIntent = new Intent(context, MediaActivity.class); + Bundle b = new Bundle(); + b.putInt(Helper.ARG_MEDIA_POSITION, 1); + ArrayList attachments = new ArrayList<>(); + attachments.add(status.art_attachment); + b.putSerializable(Helper.ARG_MEDIA_ARRAY, attachments); + mediaIntent.putExtras(b); + ActivityOptionsCompat options = ActivityOptionsCompat + .makeSceneTransitionAnimation((Activity) context, holder.bindingArt.artMedia, status.art_attachment.url); + context.startActivity(mediaIntent, options.toBundle()); + }); + holder.bindingArt.bottomBanner.setOnClickListener(v -> { + Intent intent = new Intent(context, ContextActivity.class); + intent.putExtra(Helper.ARG_STATUS, status); + context.startActivity(intent); + }); } } @@ -1625,6 +1675,7 @@ public class StatusAdapter extends RecyclerView.Adapter DrawerStatusHiddenBinding bindingHidden; DrawerStatusReportBinding bindingReport; DrawerStatusNotificationBinding bindingNotification; + DrawerStatusArtBinding bindingArt; Timer timer; StatusViewHolder(DrawerStatusBinding itemView) { @@ -1649,6 +1700,10 @@ public class StatusAdapter extends RecyclerView.Adapter bindingHidden = itemView; } + StatusViewHolder(DrawerStatusArtBinding itemView) { + super(itemView.getRoot()); + bindingArt = itemView; + } } 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 9ac7338f2..44f2dc0e1 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 @@ -45,6 +45,7 @@ import app.fedilab.android.client.entities.QuickLoad; import app.fedilab.android.client.entities.Timeline; import app.fedilab.android.client.entities.app.TagTimeline; import app.fedilab.android.client.mastodon.entities.Account; +import app.fedilab.android.client.mastodon.entities.Attachment; import app.fedilab.android.client.mastodon.entities.Marker; import app.fedilab.android.client.mastodon.entities.Pagination; import app.fedilab.android.client.mastodon.entities.Status; @@ -178,6 +179,9 @@ public class FragmentMastodonTimeline extends Fragment { } if (tagTimeline != null) { ident = tagTimeline.name; + if (tagTimeline.isART) { + timelineType = Timeline.TimeLineEnum.ART; + } } else if (list_id != null) { ident = list_id; } else if (remoteInstance != null) { @@ -252,6 +256,27 @@ public class FragmentMastodonTimeline extends Fragment { if (statuses == null || statuses.statuses == null || statuses.statuses.size() == 0) { binding.noAction.setVisibility(View.VISIBLE); return; + } else if (timelineType == Timeline.TimeLineEnum.ART) { + //We have to split media in different statuses + List mediaStatuses = new ArrayList<>(); + for (Status status : statuses.statuses) { + if (!tagTimeline.isNSFW && status.sensitive) { + continue; + } + for (Attachment attachment : status.media_attachments) { + try { + Status statusTmp = (Status) status.clone(); + statusTmp.art_attachment = attachment; + mediaStatuses.add(statusTmp); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + + } + } + if (mediaStatuses.size() > 0) { + statuses.statuses = mediaStatuses; + } } binding.recyclerView.setVisibility(View.VISIBLE); @@ -333,6 +358,21 @@ public class FragmentMastodonTimeline extends Fragment { } binding.loadingNextElements.setVisibility(View.GONE); if (statuses != null && fetched_statuses != null && fetched_statuses.statuses != null) { + + if (timelineType == Timeline.TimeLineEnum.ART) { + //We have to split media in different statuses + List mediaStatuses = new ArrayList<>(); + for (Status status : fetched_statuses.statuses) { + if (status.media_attachments.size() > 1) { + for (Attachment attachment : status.media_attachments) { + status.media_attachments = new ArrayList<>(); + status.media_attachments.add(0, attachment); + mediaStatuses.add(status); + } + } + } + fetched_statuses.statuses = mediaStatuses; + } //There are some statuses present in the timeline int startId = statuses.size(); if (direction == DIRECTION.TOP) { @@ -492,7 +532,7 @@ public class FragmentMastodonTimeline extends Fragment { timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, min_id, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP)); } - } else if (timelineType == Timeline.TimeLineEnum.TAG) { //TAG TIMELINE + } else if (timelineType == Timeline.TimeLineEnum.TAG || timelineType == Timeline.TimeLineEnum.ART) { //TAG TIMELINE if (tagTimeline == null) { tagTimeline = new TagTimeline(); tagTimeline.name = search; diff --git a/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabPageAdapter.java b/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabPageAdapter.java index af5e49d47..541ff4842 100644 --- a/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabPageAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabPageAdapter.java @@ -85,8 +85,7 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter { if (pinnedTimeline.type == Timeline.TimeLineEnum.LIST) { bundle.putString(Helper.ARG_LIST_ID, pinnedTimeline.mastodonList.id); } else if (pinnedTimeline.type == Timeline.TimeLineEnum.TAG) { - String tag = pinnedTimeline.tagTimeline.name.replaceAll("#", ""); - bundle.putString(Helper.ARG_SEARCH_KEYWORD, tag); + bundle.putSerializable(Helper.ARG_TAG_TIMELINE, pinnedTimeline.tagTimeline); } else if (pinnedTimeline.type == Timeline.TimeLineEnum.REMOTE) { String instance = pinnedTimeline.remoteInstance.host; bundle.putString(Helper.ARG_REMOTE_INSTANCE, instance); diff --git a/app/src/main/res/layout/drawer_status_art.xml b/app/src/main/res/layout/drawer_status_art.xml new file mode 100644 index 000000000..d14d14c4f --- /dev/null +++ b/app/src/main/res/layout/drawer_status_art.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file