mirror of
https://codeberg.org/tom79/Fedilab.git
synced 2024-12-22 16:50:04 +02:00
Art timelines
This commit is contained in:
parent
b16fc7b1a9
commit
a8afc99401
9 changed files with 289 additions and 76 deletions
|
@ -73,7 +73,6 @@ import com.jaredrummler.cyanea.Cyanea;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -122,7 +121,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
|
||||||
public static Account.API api;
|
public static Account.API api;
|
||||||
public static boolean admin;
|
public static boolean admin;
|
||||||
public static WeakReference<Account> accountWeakReference;
|
public static WeakReference<Account> accountWeakReference;
|
||||||
public static HashMap<Integer, Fragment> mPageReferenceMap;
|
|
||||||
public static status networkAvailable = UNKNOWN;
|
public static status networkAvailable = UNKNOWN;
|
||||||
public static Instance instanceInfo;
|
public static Instance instanceInfo;
|
||||||
public static List<Filter> mainFilters;
|
public static List<Filter> mainFilters;
|
||||||
|
|
|
@ -364,6 +364,8 @@ public class Timeline {
|
||||||
PUBLIC("PUBLIC"),
|
PUBLIC("PUBLIC"),
|
||||||
@SerializedName("TAG")
|
@SerializedName("TAG")
|
||||||
TAG("TAG"),
|
TAG("TAG"),
|
||||||
|
@SerializedName("ART")
|
||||||
|
ART("ART"),
|
||||||
@SerializedName("LIST")
|
@SerializedName("LIST")
|
||||||
LIST("LIST"),
|
LIST("LIST"),
|
||||||
@SerializedName("REMOTE")
|
@SerializedName("REMOTE")
|
||||||
|
|
|
@ -16,13 +16,15 @@ package app.fedilab.android.client.mastodon.entities;
|
||||||
|
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Status implements Serializable {
|
public class Status implements Serializable, Cloneable {
|
||||||
|
|
||||||
@SerializedName("id")
|
@SerializedName("id")
|
||||||
public String id;
|
public String id;
|
||||||
|
@ -83,6 +85,9 @@ public class Status implements Serializable {
|
||||||
@SerializedName("poll")
|
@SerializedName("poll")
|
||||||
public Poll poll;
|
public Poll poll;
|
||||||
|
|
||||||
|
|
||||||
|
public Attachment art_attachment;
|
||||||
|
|
||||||
//Some extra spannable element - They will be filled automatically when fetching the status
|
//Some extra spannable element - They will be filled automatically when fetching the status
|
||||||
public transient Spannable span_content;
|
public transient Spannable span_content;
|
||||||
public transient Spannable span_spoiler_text;
|
public transient Spannable span_spoiler_text;
|
||||||
|
@ -98,4 +103,9 @@ public class Status implements Serializable {
|
||||||
public transient boolean setCursorToEnd = false;
|
public transient boolean setCursorToEnd = false;
|
||||||
public transient int cursorPosition = 0;
|
public transient int cursorPosition = 0;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
import static app.fedilab.android.BaseMainActivity.mPageReferenceMap;
|
|
||||||
import static app.fedilab.android.ui.pageadapter.FedilabPageAdapter.BOTTOM_TIMELINE_COUNT;
|
import static app.fedilab.android.ui.pageadapter.FedilabPageAdapter.BOTTOM_TIMELINE_COUNT;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -192,10 +191,10 @@ public class PinnedTimelineHelper {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TAG:
|
case TAG:
|
||||||
tagClick(activity, finalPinned, v, finalI);
|
tagClick(activity, finalPinned, v, activityMainBinding, finalI);
|
||||||
break;
|
break;
|
||||||
case REMOTE:
|
case REMOTE:
|
||||||
instanceClick(activity, finalPinned, v, finalI);
|
instanceClick(activity, finalPinned, v, activityMainBinding, finalI);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -265,7 +264,7 @@ public class PinnedTimelineHelper {
|
||||||
* @param view - View
|
* @param view - View
|
||||||
* @param position - int position of the tab
|
* @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);
|
PopupMenu popup = new PopupMenu(new ContextThemeWrapper(context, Helper.popupStyle()), view);
|
||||||
int offSetPosition = position - BOTTOM_TIMELINE_COUNT;
|
int offSetPosition = position - BOTTOM_TIMELINE_COUNT;
|
||||||
|
@ -295,24 +294,23 @@ public class PinnedTimelineHelper {
|
||||||
itemShowNSFW.setChecked(showNSFW[0]);
|
itemShowNSFW.setChecked(showNSFW[0]);
|
||||||
popup.setOnDismissListener(menu1 -> {
|
popup.setOnDismissListener(menu1 -> {
|
||||||
if (changes[0]) {
|
if (changes[0]) {
|
||||||
if (mPageReferenceMap == null)
|
FragmentMastodonTimeline fragmentMastodonTimeline;
|
||||||
return;
|
if (activityMainBinding.viewPager.getAdapter() != null) {
|
||||||
FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition());
|
||||||
FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position);
|
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
|
||||||
if (fragmentMastodonTimeline == null)
|
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
|
||||||
return;
|
FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
fragTransaction.detach(fragmentMastodonTimeline);
|
fragTransaction.detach(fragmentMastodonTimeline).commit();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("tag", tagTimeline.name);
|
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG);
|
||||||
bundle.putInt("timelineId", tagTimeline.id);
|
bundle.putSerializable(Helper.ARG_TAG_TIMELINE, tagTimeline);
|
||||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TAG);
|
fragmentMastodonTimeline.setArguments(bundle);
|
||||||
if (mediaOnly[0])
|
FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
bundle.putString("instanceType", "ART");
|
fragTransaction2.attach(fragmentMastodonTimeline);
|
||||||
else
|
fragTransaction2.commit();
|
||||||
bundle.putString("instanceType", "MASTODON");
|
}
|
||||||
fragmentMastodonTimeline.setArguments(bundle);
|
}
|
||||||
fragTransaction.attach(fragmentMastodonTimeline);
|
|
||||||
fragTransaction.commit();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -479,7 +477,7 @@ public class PinnedTimelineHelper {
|
||||||
* @param view - View
|
* @param view - View
|
||||||
* @param position - int position of the tab
|
* @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);
|
PopupMenu popup = new PopupMenu(new ContextThemeWrapper(context, Helper.popupStyle()), view);
|
||||||
int offSetPosition = position - BOTTOM_TIMELINE_COUNT;
|
int offSetPosition = position - BOTTOM_TIMELINE_COUNT;
|
||||||
|
@ -512,12 +510,17 @@ public class PinnedTimelineHelper {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
changes[0] = true;
|
changes[0] = true;
|
||||||
FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
FragmentMastodonTimeline fragmentMastodonTimeline = null;
|
||||||
if (mPageReferenceMap == null)
|
if (activityMainBinding.viewPager.getAdapter() != null) {
|
||||||
return true;
|
Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition());
|
||||||
FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position);
|
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
|
||||||
|
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fragmentMastodonTimeline == null)
|
if (fragmentMastodonTimeline == null)
|
||||||
return false;
|
return false;
|
||||||
|
FragmentTransaction fragTransaction1 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
|
|
||||||
pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = null;
|
pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = null;
|
||||||
remoteInstance.filteredWith = null;
|
remoteInstance.filteredWith = null;
|
||||||
currentFilter[0] = null;
|
currentFilter[0] = null;
|
||||||
|
@ -527,15 +530,16 @@ public class PinnedTimelineHelper {
|
||||||
} catch (DBException e) {
|
} catch (DBException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
fragTransaction.detach(fragmentMastodonTimeline);
|
fragTransaction1.detach(fragmentMastodonTimeline).commit();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : "");
|
bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : "");
|
||||||
bundle.putString("instanceType", remoteInstance.type.getValue());
|
bundle.putString("instanceType", remoteInstance.type.getValue());
|
||||||
bundle.putString("timelineId", remoteInstance.id);
|
bundle.putString("timelineId", remoteInstance.id);
|
||||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
|
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
|
||||||
fragmentMastodonTimeline.setArguments(bundle);
|
fragmentMastodonTimeline.setArguments(bundle);
|
||||||
fragTransaction.attach(fragmentMastodonTimeline);
|
FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
fragTransaction.commit();
|
fragTransaction2.attach(fragmentMastodonTimeline);
|
||||||
|
fragTransaction2.commit();
|
||||||
popup.getMenu().close();
|
popup.getMenu().close();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -553,10 +557,15 @@ public class PinnedTimelineHelper {
|
||||||
}
|
}
|
||||||
MenuItem item = popup.getMenu().add(0, 0, Menu.NONE, title);
|
MenuItem item = popup.getMenu().add(0, 0, Menu.NONE, title);
|
||||||
item.setOnMenuItemClickListener(item1 -> {
|
item.setOnMenuItemClickListener(item1 -> {
|
||||||
FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
FragmentMastodonTimeline fragmentMastodonTimeline = null;
|
||||||
if (mPageReferenceMap == null)
|
if (activityMainBinding.viewPager.getAdapter() != null) {
|
||||||
return true;
|
Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition());
|
||||||
FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position);
|
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
|
||||||
|
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
|
||||||
|
fragmentMastodonTimeline.refreshAllAdapters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FragmentTransaction fragTransaction1 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
if (fragmentMastodonTimeline == null)
|
if (fragmentMastodonTimeline == null)
|
||||||
return false;
|
return false;
|
||||||
pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = tag;
|
pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = tag;
|
||||||
|
@ -567,7 +576,7 @@ public class PinnedTimelineHelper {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
currentFilter[0] = remoteInstance.filteredWith;
|
currentFilter[0] = remoteInstance.filteredWith;
|
||||||
fragTransaction.detach(fragmentMastodonTimeline);
|
fragTransaction1.detach(fragmentMastodonTimeline).commit();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : "");
|
bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : "");
|
||||||
bundle.putString("instanceType", remoteInstance.type.getValue());
|
bundle.putString("instanceType", remoteInstance.type.getValue());
|
||||||
|
@ -575,8 +584,9 @@ public class PinnedTimelineHelper {
|
||||||
bundle.putString("currentfilter", remoteInstance.filteredWith);
|
bundle.putString("currentfilter", remoteInstance.filteredWith);
|
||||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
|
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
|
||||||
fragmentMastodonTimeline.setArguments(bundle);
|
fragmentMastodonTimeline.setArguments(bundle);
|
||||||
fragTransaction.attach(fragmentMastodonTimeline);
|
FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
fragTransaction.commit();
|
fragTransaction2.attach(fragmentMastodonTimeline);
|
||||||
|
fragTransaction2.commit();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -621,7 +631,7 @@ public class PinnedTimelineHelper {
|
||||||
}
|
}
|
||||||
popup.getMenu().clear();
|
popup.getMenu().clear();
|
||||||
popup.getMenu().close();
|
popup.getMenu().close();
|
||||||
instanceClick(context, pinned, view, position);
|
instanceClick(context, pinned, view, activityMainBinding, position);
|
||||||
});
|
});
|
||||||
AlertDialog alertDialog = dialogBuilder.create();
|
AlertDialog alertDialog = dialogBuilder.create();
|
||||||
alertDialog.show();
|
alertDialog.show();
|
||||||
|
@ -630,13 +640,18 @@ public class PinnedTimelineHelper {
|
||||||
|
|
||||||
popup.setOnDismissListener(menu -> {
|
popup.setOnDismissListener(menu -> {
|
||||||
if (changes[0]) {
|
if (changes[0]) {
|
||||||
FragmentTransaction fragTransaction = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
FragmentMastodonTimeline fragmentMastodonTimeline = null;
|
||||||
if (mPageReferenceMap == null)
|
if (activityMainBinding.viewPager.getAdapter() != null) {
|
||||||
return;
|
Fragment fragment = (Fragment) activityMainBinding.viewPager.getAdapter().instantiateItem(activityMainBinding.viewPager, activityMainBinding.tabLayout.getSelectedTabPosition());
|
||||||
FragmentMastodonTimeline fragmentMastodonTimeline = (FragmentMastodonTimeline) mPageReferenceMap.get(pinned.pinnedTimelines.get(position).position);
|
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
|
||||||
|
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
|
||||||
|
fragmentMastodonTimeline.refreshAllAdapters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FragmentTransaction fragTransaction1 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
if (fragmentMastodonTimeline == null)
|
if (fragmentMastodonTimeline == null)
|
||||||
return;
|
return;
|
||||||
fragTransaction.detach(fragmentMastodonTimeline);
|
fragTransaction1.detach(fragmentMastodonTimeline).commit();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : "");
|
bundle.putString(Helper.ARG_REMOTE_INSTANCE, remoteInstance.host != null ? remoteInstance.host : "");
|
||||||
bundle.putString("instanceType", remoteInstance.type.getValue());
|
bundle.putString("instanceType", remoteInstance.type.getValue());
|
||||||
|
@ -646,8 +661,9 @@ public class PinnedTimelineHelper {
|
||||||
}
|
}
|
||||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
|
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
|
||||||
fragmentMastodonTimeline.setArguments(bundle);
|
fragmentMastodonTimeline.setArguments(bundle);
|
||||||
fragTransaction.attach(fragmentMastodonTimeline);
|
FragmentTransaction fragTransaction2 = ((BaseMainActivity) context).getSupportFragmentManager().beginTransaction();
|
||||||
fragTransaction.commit();
|
fragTransaction2.attach(fragmentMastodonTimeline);
|
||||||
|
fragTransaction2.commit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,9 @@ public class SpannableHelper {
|
||||||
while (matcherALink.find()) {
|
while (matcherALink.find()) {
|
||||||
int matchStart = matcherALink.start() - offSetTruncate;
|
int matchStart = matcherALink.start() - offSetTruncate;
|
||||||
int matchEnd = matchStart + matcherALink.group().length();
|
int matchEnd = matchStart + matcherALink.group().length();
|
||||||
|
if (matchEnd > content.toString().length()) {
|
||||||
|
matchEnd = content.toString().length();
|
||||||
|
}
|
||||||
final String url = content.toString().substring(matchStart, matchEnd);
|
final String url = content.toString().substring(matchStart, matchEnd);
|
||||||
String newURL = Helper.transformURL(context, url);
|
String newURL = Helper.transformURL(context, url);
|
||||||
//If URL has been transformed
|
//If URL has been transformed
|
||||||
|
|
|
@ -86,6 +86,7 @@ import com.varunest.sparkbutton.SparkButton;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.regex.Matcher;
|
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.Notification;
|
||||||
import app.fedilab.android.client.mastodon.entities.Poll;
|
import app.fedilab.android.client.mastodon.entities.Poll;
|
||||||
import app.fedilab.android.client.mastodon.entities.Status;
|
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.DrawerStatusBinding;
|
||||||
import app.fedilab.android.databinding.DrawerStatusHiddenBinding;
|
import app.fedilab.android.databinding.DrawerStatusHiddenBinding;
|
||||||
import app.fedilab.android.databinding.DrawerStatusNotificationBinding;
|
import app.fedilab.android.databinding.DrawerStatusNotificationBinding;
|
||||||
|
@ -131,6 +133,10 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
private Context context;
|
private Context context;
|
||||||
private final Timeline.TimeLineEnum timelineType;
|
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<Status> statuses, Timeline.TimeLineEnum timelineType, boolean minified) {
|
public StatusAdapter(List<Status> statuses, Timeline.TimeLineEnum timelineType, boolean minified) {
|
||||||
this.statusList = statuses;
|
this.statusList = statuses;
|
||||||
this.timelineType = timelineType;
|
this.timelineType = timelineType;
|
||||||
|
@ -188,14 +194,13 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
* Manage status, this method is also reused in notifications timelines
|
* Manage status, this method is also reused in notifications timelines
|
||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param context Timeline.TimeLineEnum timelineType
|
|
||||||
* @param statusesVM StatusesVM - For handling actions in background to the correct activity
|
* @param statusesVM StatusesVM - For handling actions in background to the correct activity
|
||||||
* @param searchVM SearchVM - For handling remote actions
|
* @param searchVM SearchVM - For handling remote actions
|
||||||
* @param holder StatusViewHolder
|
* @param holder StatusViewHolder
|
||||||
* @param adapter RecyclerView.Adapter<RecyclerView.ViewHolder> - General adapter that can be for {@link StatusAdapter} or {@link NotificationAdapter}
|
* @param adapter RecyclerView.Adapter<RecyclerView.ViewHolder> - General adapter that can be for {@link StatusAdapter} or {@link NotificationAdapter}
|
||||||
* @param statusList List<Status>
|
* @param statusList List<Status>
|
||||||
* @param notificationList List<Notification>
|
* @param notificationList List<Notification>
|
||||||
* @param timelineType Timeline.TimeLineEnum
|
* @param timelineType Timeline.TimeLineEnum timelineTypeTimeline.TimeLineEnum
|
||||||
* @param status {@link Status}
|
* @param status {@link Status}
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@ -1545,17 +1550,24 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
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
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
context = parent.getContext();
|
context = parent.getContext();
|
||||||
if (viewType == 0) {
|
if (viewType == STATUS_HIDDEN) { //Hidden statuses - ie: filtered
|
||||||
DrawerStatusHiddenBinding itemBinding = DrawerStatusHiddenBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
DrawerStatusHiddenBinding itemBinding = DrawerStatusHiddenBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
return new StatusViewHolder(itemBinding);
|
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) {
|
if (!minified) {
|
||||||
DrawerStatusBinding itemBinding = DrawerStatusBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
DrawerStatusBinding itemBinding = DrawerStatusBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
return new StatusViewHolder(itemBinding);
|
return new StatusViewHolder(itemBinding);
|
||||||
|
@ -1581,29 +1593,67 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
Status status = statusList.get(position);
|
Status status = statusList.get(position);
|
||||||
StatusViewHolder holder = (StatusViewHolder) viewHolder;
|
if (viewHolder.getItemViewType() == STATUS_VISIBLE) {
|
||||||
StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class);
|
StatusViewHolder holder = (StatusViewHolder) viewHolder;
|
||||||
SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class);
|
StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class);
|
||||||
statusManagement(context, statusesVM, searchVM, holder, this, statusList, null, status, timelineType, minified);
|
SearchVM searchVM = new ViewModelProvider((ViewModelStoreOwner) context).get(SearchVM.class);
|
||||||
if (holder.timer != null) {
|
statusManagement(context, statusesVM, searchVM, holder, this, statusList, null, status, timelineType, minified);
|
||||||
holder.timer.cancel();
|
if (holder.timer != null) {
|
||||||
holder.timer = null;
|
holder.timer.cancel();
|
||||||
}
|
holder.timer = null;
|
||||||
if (status.emojis != null && status.emojis.size() > 0) {
|
}
|
||||||
holder.timer = new Timer();
|
if (status.emojis != null && status.emojis.size() > 0) {
|
||||||
holder.timer.scheduleAtFixedRate(new TimerTask() {
|
holder.timer = new Timer();
|
||||||
@Override
|
holder.timer.scheduleAtFixedRate(new TimerTask() {
|
||||||
public void run() {
|
@Override
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
public void run() {
|
||||||
Runnable myRunnable = () -> holder.binding.statusContent.invalidate();
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
mainHandler.post(myRunnable);
|
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<Attachment> 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<RecyclerView.ViewHolder>
|
||||||
DrawerStatusHiddenBinding bindingHidden;
|
DrawerStatusHiddenBinding bindingHidden;
|
||||||
DrawerStatusReportBinding bindingReport;
|
DrawerStatusReportBinding bindingReport;
|
||||||
DrawerStatusNotificationBinding bindingNotification;
|
DrawerStatusNotificationBinding bindingNotification;
|
||||||
|
DrawerStatusArtBinding bindingArt;
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
|
||||||
StatusViewHolder(DrawerStatusBinding itemView) {
|
StatusViewHolder(DrawerStatusBinding itemView) {
|
||||||
|
@ -1649,6 +1700,10 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
bindingHidden = itemView;
|
bindingHidden = itemView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusViewHolder(DrawerStatusArtBinding itemView) {
|
||||||
|
super(itemView.getRoot());
|
||||||
|
bindingArt = itemView;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ import app.fedilab.android.client.entities.QuickLoad;
|
||||||
import app.fedilab.android.client.entities.Timeline;
|
import app.fedilab.android.client.entities.Timeline;
|
||||||
import app.fedilab.android.client.entities.app.TagTimeline;
|
import app.fedilab.android.client.entities.app.TagTimeline;
|
||||||
import app.fedilab.android.client.mastodon.entities.Account;
|
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.Marker;
|
||||||
import app.fedilab.android.client.mastodon.entities.Pagination;
|
import app.fedilab.android.client.mastodon.entities.Pagination;
|
||||||
import app.fedilab.android.client.mastodon.entities.Status;
|
import app.fedilab.android.client.mastodon.entities.Status;
|
||||||
|
@ -178,6 +179,9 @@ public class FragmentMastodonTimeline extends Fragment {
|
||||||
}
|
}
|
||||||
if (tagTimeline != null) {
|
if (tagTimeline != null) {
|
||||||
ident = tagTimeline.name;
|
ident = tagTimeline.name;
|
||||||
|
if (tagTimeline.isART) {
|
||||||
|
timelineType = Timeline.TimeLineEnum.ART;
|
||||||
|
}
|
||||||
} else if (list_id != null) {
|
} else if (list_id != null) {
|
||||||
ident = list_id;
|
ident = list_id;
|
||||||
} else if (remoteInstance != null) {
|
} else if (remoteInstance != null) {
|
||||||
|
@ -252,6 +256,27 @@ public class FragmentMastodonTimeline extends Fragment {
|
||||||
if (statuses == null || statuses.statuses == null || statuses.statuses.size() == 0) {
|
if (statuses == null || statuses.statuses == null || statuses.statuses.size() == 0) {
|
||||||
binding.noAction.setVisibility(View.VISIBLE);
|
binding.noAction.setVisibility(View.VISIBLE);
|
||||||
return;
|
return;
|
||||||
|
} else if (timelineType == Timeline.TimeLineEnum.ART) {
|
||||||
|
//We have to split media in different statuses
|
||||||
|
List<Status> 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);
|
binding.recyclerView.setVisibility(View.VISIBLE);
|
||||||
|
@ -333,6 +358,21 @@ public class FragmentMastodonTimeline extends Fragment {
|
||||||
}
|
}
|
||||||
binding.loadingNextElements.setVisibility(View.GONE);
|
binding.loadingNextElements.setVisibility(View.GONE);
|
||||||
if (statuses != null && fetched_statuses != null && fetched_statuses.statuses != null) {
|
if (statuses != null && fetched_statuses != null && fetched_statuses.statuses != null) {
|
||||||
|
|
||||||
|
if (timelineType == Timeline.TimeLineEnum.ART) {
|
||||||
|
//We have to split media in different statuses
|
||||||
|
List<Status> 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
|
//There are some statuses present in the timeline
|
||||||
int startId = statuses.size();
|
int startId = statuses.size();
|
||||||
if (direction == DIRECTION.TOP) {
|
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()))
|
timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, min_id, MastodonHelper.statusesPerCall(requireActivity()))
|
||||||
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP));
|
.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) {
|
if (tagTimeline == null) {
|
||||||
tagTimeline = new TagTimeline();
|
tagTimeline = new TagTimeline();
|
||||||
tagTimeline.name = search;
|
tagTimeline.name = search;
|
||||||
|
|
|
@ -85,8 +85,7 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter {
|
||||||
if (pinnedTimeline.type == Timeline.TimeLineEnum.LIST) {
|
if (pinnedTimeline.type == Timeline.TimeLineEnum.LIST) {
|
||||||
bundle.putString(Helper.ARG_LIST_ID, pinnedTimeline.mastodonList.id);
|
bundle.putString(Helper.ARG_LIST_ID, pinnedTimeline.mastodonList.id);
|
||||||
} else if (pinnedTimeline.type == Timeline.TimeLineEnum.TAG) {
|
} else if (pinnedTimeline.type == Timeline.TimeLineEnum.TAG) {
|
||||||
String tag = pinnedTimeline.tagTimeline.name.replaceAll("#", "");
|
bundle.putSerializable(Helper.ARG_TAG_TIMELINE, pinnedTimeline.tagTimeline);
|
||||||
bundle.putString(Helper.ARG_SEARCH_KEYWORD, tag);
|
|
||||||
} else if (pinnedTimeline.type == Timeline.TimeLineEnum.REMOTE) {
|
} else if (pinnedTimeline.type == Timeline.TimeLineEnum.REMOTE) {
|
||||||
String instance = pinnedTimeline.remoteInstance.host;
|
String instance = pinnedTimeline.remoteInstance.host;
|
||||||
bundle.putString(Helper.ARG_REMOTE_INSTANCE, instance);
|
bundle.putString(Helper.ARG_REMOTE_INSTANCE, instance);
|
||||||
|
|
91
app/src/main/res/layout/drawer_status_art.xml
Normal file
91
app/src/main/res/layout/drawer_status_art.xml
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
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 <http://www.gnu.org/licenses>.
|
||||||
|
-->
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/art_media"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerInside" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/status_show_more"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:background="@color/mastodonC1"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/show_more_button_art"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:src="@drawable/ic_outline_remove_red_eye_24" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/bottom_banner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:background="#44000000"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/art_pp"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_gravity="center" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/art_author"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/art_username"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/art_acct"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/white" />
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in a new issue