forked from mirrors/Fedilab
Add Bubble timeline support
This commit is contained in:
parent
818f32ffb5
commit
f976b6dd72
8 changed files with 84 additions and 60 deletions
|
@ -53,6 +53,19 @@ public interface MastodonTimelinesService {
|
|||
@Query("limit") Integer limit
|
||||
);
|
||||
|
||||
@GET("timelines/bubble")
|
||||
Call<List<Status>> getBubble(
|
||||
@Header("Authorization") String token,
|
||||
@Query("only_media") Boolean only_media,
|
||||
@Query("remote") Boolean remote,
|
||||
@Query("with_muted") Boolean with_muted,
|
||||
@Query("exclude_visibilities") List<String> exclude_visibilities,
|
||||
@Query("reply_visibility") String reply_visibility,
|
||||
@Query("max_id") String max_id,
|
||||
@Query("since_id") String since_id,
|
||||
@Query("min_id") String min_id,
|
||||
@Query("limit") Integer limit
|
||||
);
|
||||
|
||||
@GET("trends/statuses")
|
||||
Call<List<Status>> getStatusTrends(
|
||||
|
|
|
@ -364,6 +364,8 @@ public class Timeline {
|
|||
LOCAL("LOCAL"),
|
||||
@SerializedName("PUBLIC")
|
||||
PUBLIC("PUBLIC"),
|
||||
@SerializedName("BUBBLE")
|
||||
BUBBLE("BUBBLE"),
|
||||
@SerializedName("CONTEXT")
|
||||
CONTEXT("CONTEXT"),
|
||||
@SerializedName("TAG")
|
||||
|
|
|
@ -22,7 +22,6 @@ import static app.fedilab.android.BaseMainActivity.show_replies;
|
|||
import static app.fedilab.android.ui.pageadapter.FedilabPageAdapter.BOTTOM_TIMELINE_COUNT;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
|
@ -57,6 +56,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
import app.fedilab.android.client.entities.api.MastodonList;
|
||||
import app.fedilab.android.client.entities.app.BottomMenu;
|
||||
import app.fedilab.android.client.entities.app.Pinned;
|
||||
|
@ -94,59 +94,6 @@ public class PinnedTimelineHelper {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the slug of the first loaded fragment
|
||||
*
|
||||
* @param context - Context
|
||||
* @param pinned - {@link Pinned}
|
||||
* @param bottomMenu - {@link BottomMenu}
|
||||
* @return String - slug
|
||||
*/
|
||||
public static String firstTimelineSlug(Context context, Pinned pinned, BottomMenu bottomMenu) {
|
||||
String slug = Timeline.TimeLineEnum.HOME.getValue();
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean singleBar = sharedpreferences.getBoolean(context.getString(R.string.SET_USE_SINGLE_TOPBAR), false);
|
||||
PinnedTimeline pinnedTimelineMin = null;
|
||||
if (singleBar) {
|
||||
if (pinned != null && pinned.pinnedTimelines != null) {
|
||||
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
|
||||
if (pinnedTimeline.displayed) {
|
||||
if (pinnedTimelineMin == null) {
|
||||
pinnedTimelineMin = pinnedTimeline;
|
||||
} else if (pinnedTimelineMin.position > pinnedTimeline.position) {
|
||||
pinnedTimelineMin = pinnedTimeline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bottomMenu != null && bottomMenu.bottom_menu != null && bottomMenu.bottom_menu.size() > 0) {
|
||||
BottomMenu.MenuItem menuItem = bottomMenu.bottom_menu.get(0);
|
||||
return menuItem.item_menu_type.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
String ident = null;
|
||||
if (pinnedTimelineMin != null) {
|
||||
if (pinnedTimelineMin.tagTimeline != null) {
|
||||
ident = "@T@" + pinnedTimelineMin.tagTimeline.name;
|
||||
if (pinnedTimelineMin.tagTimeline.isART) {
|
||||
pinnedTimelineMin.type = Timeline.TimeLineEnum.ART;
|
||||
}
|
||||
} else if (pinnedTimelineMin.mastodonList != null) {
|
||||
ident = "@l@" + pinnedTimelineMin.mastodonList.id;
|
||||
} else if (pinnedTimelineMin.remoteInstance != null) {
|
||||
if (pinnedTimelineMin.remoteInstance.type == RemoteInstance.InstanceType.NITTER) {
|
||||
String remoteInstance = sharedpreferences.getString(context.getString(R.string.SET_NITTER_HOST), context.getString(R.string.DEFAULT_NITTER_HOST)).toLowerCase();
|
||||
ident = "@R@" + remoteInstance;
|
||||
} else {
|
||||
ident = "@R@" + pinnedTimelineMin.remoteInstance.host;
|
||||
}
|
||||
}
|
||||
slug = pinnedTimelineMin.type.getValue() + (ident != null ? "|" + ident : "");
|
||||
}
|
||||
return slug;
|
||||
}
|
||||
|
||||
public synchronized static void redrawTopBarPinned(BaseMainActivity activity, ActivityMainBinding activityMainBinding, Pinned pinned, BottomMenu bottomMenu, List<MastodonList> mastodonLists) {
|
||||
//Values must be initialized if there is no records in db
|
||||
|
@ -159,8 +106,8 @@ public class PinnedTimelineHelper {
|
|||
pinned.pinnedTimelines = new ArrayList<>();
|
||||
}
|
||||
//Set the slug of first visible fragment
|
||||
String slugOfFirstFragment = PinnedTimelineHelper.firstTimelineSlug(activity, pinned, bottomMenu);
|
||||
Helper.setSlugOfFirstFragment(activity, slugOfFirstFragment, currentUserID, currentInstance);
|
||||
/*String slugOfFirstFragment = PinnedTimelineHelper.firstTimelineSlug(activity, pinned, bottomMenu);
|
||||
Helper.setSlugOfFirstFragment(activity, slugOfFirstFragment, currentUserID, currentInstance);*/
|
||||
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
boolean singleBar = sharedpreferences.getBoolean(activity.getString(R.string.SET_USE_SINGLE_TOPBAR), false);
|
||||
|
@ -187,6 +134,7 @@ public class PinnedTimelineHelper {
|
|||
|
||||
activityMainBinding.viewPager.setLayoutParams(params);
|
||||
List<PinnedTimeline> pinnedTimelines = pinned.pinnedTimelines;
|
||||
boolean extraFeatures = sharedpreferences.getBoolean(activity.getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, false);
|
||||
|
||||
if (singleBar) {
|
||||
boolean createDefaultAtTop = true;
|
||||
|
@ -222,15 +170,40 @@ public class PinnedTimelineHelper {
|
|||
pinnedTimelineConversations.type = Timeline.TimeLineEnum.DIRECT;
|
||||
pinnedTimelineConversations.position = 4;
|
||||
pinned.pinnedTimelines.add(pinnedTimelineConversations);
|
||||
|
||||
try {
|
||||
new Pinned(activity).updatePinned(pinned);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (extraFeatures) {
|
||||
try {
|
||||
Pinned pinnedAll = new Pinned(activity).getAllPinned(currentAccount);
|
||||
boolean createDefaultBubbleAtTop = true;
|
||||
for (PinnedTimeline pinnedTimeline : pinnedAll.pinnedTimelines) {
|
||||
if (pinnedTimeline.type == Timeline.TimeLineEnum.BUBBLE) {
|
||||
createDefaultBubbleAtTop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (createDefaultBubbleAtTop) {
|
||||
PinnedTimeline pinnedTimelineBubble = new PinnedTimeline();
|
||||
pinnedTimelineBubble.type = Timeline.TimeLineEnum.BUBBLE;
|
||||
pinnedTimelineBubble.position = pinnedAll.pinnedTimelines != null ? pinnedAll.pinnedTimelines.size() : 0;
|
||||
pinned.pinnedTimelines.add(pinnedTimelineBubble);
|
||||
boolean exist = new Pinned(activity).pinnedExist(pinned);
|
||||
if (exist) {
|
||||
new Pinned(activity).updatePinned(pinned);
|
||||
} else {
|
||||
new Pinned(activity).insertPinned(pinned);
|
||||
}
|
||||
}
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
sortPositionAsc(pinnedTimelines);
|
||||
//Check if changes occurred, if mastodonLists is null it does need, because it is the first call to draw pinned
|
||||
boolean needRedraw = mastodonLists == null;
|
||||
|
@ -421,6 +394,9 @@ public class PinnedTimelineHelper {
|
|||
case DIRECT:
|
||||
tabCustomDefaultViewBinding.icon.setImageResource(R.drawable.ic_baseline_mail_24);
|
||||
break;
|
||||
case BUBBLE:
|
||||
tabCustomDefaultViewBinding.icon.setImageResource(R.drawable.ic_baseline_bubble_chart_24);
|
||||
break;
|
||||
}
|
||||
tab.setCustomView(tabCustomDefaultViewBinding.getRoot());
|
||||
}
|
||||
|
|
|
@ -141,6 +141,10 @@ public class ReorderTabAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
|||
holder.binding.icon.setImageResource(R.drawable.ic_baseline_mail_24);
|
||||
holder.binding.text.setText(R.string.v_direct);
|
||||
break;
|
||||
case BUBBLE:
|
||||
holder.binding.icon.setImageResource(R.drawable.ic_baseline_bubble_chart_24);
|
||||
holder.binding.text.setText(R.string.bubble);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ package app.fedilab.android.ui.fragment.timeline;
|
|||
|
||||
|
||||
import static app.fedilab.android.BaseMainActivity.currentInstance;
|
||||
import static app.fedilab.android.BaseMainActivity.currentUserID;
|
||||
import static app.fedilab.android.BaseMainActivity.networkAvailable;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
|
@ -342,6 +341,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
minified = getArguments().getBoolean(Helper.ARG_MINIFIED, false);
|
||||
statusReport = (Status) getArguments().getSerializable(Helper.ARG_STATUS_REPORT);
|
||||
}
|
||||
|
||||
//When visiting a profile without being authenticated
|
||||
if (checkRemotely) {
|
||||
String[] acctArray = accountTimeline.acct.split("@");
|
||||
|
@ -619,7 +619,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
}
|
||||
});
|
||||
//For first tab we fetch new messages, if we keep position
|
||||
if (slug != null && slug.compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) == 0 && rememberPosition) {
|
||||
if (slug != null /*&& slug.compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) == 0*/ && rememberPosition) {
|
||||
route(DIRECTION.FETCH_NEW, true);
|
||||
}
|
||||
}
|
||||
|
@ -712,6 +712,10 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
timelineParams.local = false;
|
||||
timelineParams.remote = true;
|
||||
break;
|
||||
case BUBBLE:
|
||||
timelineParams.onlyMedia = false;
|
||||
timelineParams.remote = false;
|
||||
break;
|
||||
case LIST:
|
||||
timelineParams.listId = list_id;
|
||||
break;
|
||||
|
@ -898,6 +902,8 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
|
|||
routeCommon(direction, fetchingMissing, statusToUpdate);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.PUBLIC) { //PUBLIC TIMELINE
|
||||
routeCommon(direction, fetchingMissing, statusToUpdate);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.BUBBLE) { //BUBBLE TIMELINE
|
||||
routeCommon(direction, fetchingMissing, statusToUpdate);
|
||||
} else if (timelineType == Timeline.TimeLineEnum.REMOTE) { //REMOTE TIMELINE
|
||||
//NITTER TIMELINES
|
||||
if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER) {
|
||||
|
|
|
@ -417,6 +417,9 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
case PUBLIC:
|
||||
timelineCall = mastodonTimelinesService.getPublic(timelineParams.token, false, true, timelineParams.onlyMedia, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
break;
|
||||
case BUBBLE:
|
||||
timelineCall = mastodonTimelinesService.getBubble(timelineParams.token, timelineParams.onlyMedia, timelineParams.remote, timelineParams.withMuted, timelineParams.excludeVisibilities, timelineParams.replyVisibility, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
break;
|
||||
case ART:
|
||||
case TAG:
|
||||
timelineCall = mastodonTimelinesService.getHashTag(timelineParams.token, timelineParams.hashtagTrim, timelineParams.local, timelineParams.onlyMedia, timelineParams.all, timelineParams.any, timelineParams.none, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit);
|
||||
|
@ -949,6 +952,7 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
public String userId;
|
||||
public Boolean remote;
|
||||
public Boolean onlyMedia;
|
||||
public Boolean withMuted;
|
||||
public String hashtagTrim;
|
||||
public List<String> all;
|
||||
public List<String> any;
|
||||
|
@ -961,6 +965,8 @@ public class TimelinesVM extends AndroidViewModel {
|
|||
public int limit = 40;
|
||||
public Boolean local;
|
||||
public List<String> excludeType;
|
||||
public List<String> excludeVisibilities;
|
||||
public String replyVisibility;
|
||||
|
||||
public TimelineParams(@NonNull Timeline.TimeLineEnum timeLineEnum, @Nullable FragmentMastodonTimeline.DIRECTION timelineDirection, @Nullable String ident) {
|
||||
if (type != Timeline.TimeLineEnum.REMOTE) {
|
||||
|
|
16
app/src/main/res/drawable/ic_baseline_bubble_chart_24.xml
Normal file
16
app/src/main/res/drawable/ic_baseline_bubble_chart_24.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#FFFFFF"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M7.2,14.4m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14.8,18m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M15.2,8.8m-4.8,0a4.8,4.8 0,1 1,9.6 0a4.8,4.8 0,1 1,-9.6 0" />
|
||||
</vector>
|
|
@ -2174,4 +2174,5 @@
|
|||
<string name="icons_extra_features_visibility_summary">If your instance does not accept some extra features, you can hide these icons</string>
|
||||
<string name="set_display_quote_indication">Display the \"Quote\" button</string>
|
||||
<string name="set_display_reaction_indication">Display \"Reactions\" buttons</string>
|
||||
<string name="bubble">Bubble</string>
|
||||
</resources>
|
Loading…
Reference in a new issue