summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas <tschneider.ac@gmail.com>2022-06-11 18:19:37 +0200
committerThomas <tschneider.ac@gmail.com>2022-06-11 18:19:37 +0200
commit6b043fc451fde7bce3384021f5a7b88cf68c2967 (patch)
treea7f886813a3219a0e1f46d947d3cbc34426a6588
parent77e90ff41f2b3b53f300e6f67e6c303358de023e (diff)
Timeline keep position
-rw-r--r--app/src/main/java/app/fedilab/android/client/entities/api/Status.java1
-rw-r--r--app/src/main/java/app/fedilab/android/client/entities/app/StatusCache.java20
-rw-r--r--app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java25
-rw-r--r--app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java17
-rw-r--r--app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java149
-rw-r--r--app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabPageAdapter.java18
-rw-r--r--app/src/main/java/app/fedilab/android/viewmodel/mastodon/TimelinesVM.java32
-rw-r--r--app/src/main/res/layout/drawer_fetch_more.xml7
8 files changed, 190 insertions, 79 deletions
diff --git a/app/src/main/java/app/fedilab/android/client/entities/api/Status.java b/app/src/main/java/app/fedilab/android/client/entities/api/Status.java
index 80910bcb8..473f95b7b 100644
--- a/app/src/main/java/app/fedilab/android/client/entities/api/Status.java
+++ b/app/src/main/java/app/fedilab/android/client/entities/api/Status.java
@@ -95,6 +95,7 @@ public class Status implements Serializable, Cloneable {
public boolean isExpended = false;
public boolean isTruncated = true;
public boolean isFetchMore = false;
+ public boolean isFetchMoreHidden = false;
public boolean isMediaDisplayed = false;
public boolean isMediaObfuscated = true;
public boolean isChecked = false;
diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/StatusCache.java b/app/src/main/java/app/fedilab/android/client/entities/app/StatusCache.java
index 11c2b00d1..4023bc1d6 100644
--- a/app/src/main/java/app/fedilab/android/client/entities/app/StatusCache.java
+++ b/app/src/main/java/app/fedilab/android/client/entities/app/StatusCache.java
@@ -23,6 +23,7 @@ import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -284,22 +285,24 @@ public class StatusCache {
* @return Statuses
* @throws DBException - throws a db exception
*/
- public Statuses geStatuses(CacheEnum type, String instance, String user_id, String max_id, String min_id) throws DBException {
+ public Statuses geStatuses(CacheEnum type, String instance, String user_id, String max_id, String min_id, String since_id) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
+ String order = " DESC";
String selection = Sqlite.COL_INSTANCE + "='" + instance + "' AND " + Sqlite.COL_USER_ID + "= '" + user_id + "'";
String limit = String.valueOf(MastodonHelper.statusesPerCall(context));
- if (max_id == null && min_id != null) {
+ if (min_id != null) {
selection += "AND " + Sqlite.COL_STATUS_ID + " > '" + min_id + "'";
- } else if (max_id != null && min_id == null) {
- selection += "AND " + Sqlite.COL_STATUS_ID + " < '" + max_id + "'";
+ order = " ASC";
} else if (max_id != null) {
- selection += "AND " + Sqlite.COL_STATUS_ID + " > '" + min_id + "' AND " + Sqlite.COL_STATUS_ID + " < '" + max_id + "'";
+ selection += "AND " + Sqlite.COL_STATUS_ID + " < '" + max_id + "'";
+ } else if (since_id != null) {
+ selection += "AND " + Sqlite.COL_STATUS_ID + " > '" + since_id + "'";
limit = null;
}
try {
- Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, null, null, Sqlite.COL_STATUS_ID + " DESC", limit);
+ Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, null, null, Sqlite.COL_STATUS_ID + order, limit);
return createStatusReply(cursorToListOfStatuses(c));
} catch (Exception e) {
e.printStackTrace();
@@ -373,6 +376,11 @@ public class StatusCache {
statuses.statuses = statusList;
Pagination pagination = new Pagination();
if (statusList != null && statusList.size() > 0) {
+ //Status list is inverted, it happens for min_id due to ASC ordering
+ if (statusList.get(0).id.compareTo(statusList.get(statusList.size() - 1).id) < 0) {
+ Collections.reverse(statusList);
+ statuses.statuses = statusList;
+ }
pagination.max_id = statusList.get(0).id;
pagination.min_id = statusList.get(statusList.size() - 1).id;
}
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 e36cb86b3..f693096cc 100644
--- a/app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java
+++ b/app/src/main/java/app/fedilab/android/helper/PinnedTimelineHelper.java
@@ -43,6 +43,7 @@ import java.util.List;
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;
@@ -146,7 +147,8 @@ public class PinnedTimelineHelper {
//Pinned tab position will start after BOTTOM_TIMELINE_COUNT (ie 5)
activityMainBinding.tabLayout.removeAllTabs();
//Small hack to hide first tabs (they represent the item of the bottom menu)
- for (int i = 0; i < BOTTOM_TIMELINE_COUNT; i++) {
+ int toRemove = itemToRemoveInBottomMenu(activity);
+ for (int i = 0; i < BOTTOM_TIMELINE_COUNT - toRemove; i++) {
activityMainBinding.tabLayout.addTab(activityMainBinding.tabLayout.newTab());
((ViewGroup) activityMainBinding.tabLayout.getChildAt(0)).getChildAt(i).setVisibility(View.GONE);
}
@@ -203,7 +205,7 @@ public class PinnedTimelineHelper {
activityMainBinding.viewPager.clearOnPageChangeListeners();
activityMainBinding.tabLayout.clearOnTabSelectedListeners();
- FedilabPageAdapter fedilabPageAdapter = new FedilabPageAdapter(activity.getSupportFragmentManager(), pinned, bottomMenu);
+ FedilabPageAdapter fedilabPageAdapter = new FedilabPageAdapter(activity, activity.getSupportFragmentManager(), pinned, bottomMenu);
activityMainBinding.viewPager.setAdapter(fedilabPageAdapter);
activityMainBinding.viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(activityMainBinding.tabLayout));
activityMainBinding.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@@ -254,6 +256,25 @@ public class PinnedTimelineHelper {
}
+ public static int itemToRemoveInBottomMenu(Context context) {
+ //Small hack to hide first tabs (they represent the item of the bottom menu)
+ BottomMenu bottomMenuDb;
+ int toRemove = 0;
+ try {
+ //If some menu items have been hidden we should not create tab for them
+ bottomMenuDb = new BottomMenu(context).getAllBottomMenu(MainActivity.accountWeakReference.get());
+ if (bottomMenuDb != null && bottomMenuDb.bottom_menu != null) {
+ for (BottomMenu.MenuItem menuItem : bottomMenuDb.bottom_menu) {
+ if (!menuItem.visible) {
+ toRemove++;
+ }
+ }
+ }
+ } catch (DBException e) {
+ e.printStackTrace();
+ }
+ return toRemove;
+ }
/**
* Manage long clicks on Tag timelines
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 6c33b91f7..099f0d706 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
@@ -1675,6 +1675,9 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
} else if (viewType == STATUS_ART) { //Art statuses
DrawerStatusArtBinding itemBinding = DrawerStatusArtBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new StatusViewHolder(itemBinding);
+ } else if (viewType == STATUS_FETCH_MORE) { //Fetch more button
+ DrawerFetchMoreBinding itemBinding = DrawerFetchMoreBinding.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);
@@ -1764,7 +1767,19 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
});
} else if (viewHolder.getItemViewType() == STATUS_FETCH_MORE) {
StatusViewHolder holder = (StatusViewHolder) viewHolder;
- holder.bindingFetchMore.fetchMore.setOnClickListener(v -> fetchMoreCallBack.onClick(status.id));
+ if (status.isFetchMoreHidden) {
+ holder.bindingFetchMore.fetchMore.setVisibility(View.GONE);
+ } else {
+ holder.bindingFetchMore.fetchMore.setVisibility(View.VISIBLE);
+ }
+ holder.bindingFetchMore.fetchMore.setOnClickListener(v -> {
+ //We hide the button
+ status.isFetchMoreHidden = true;
+ notifyItemChanged(position);
+ if (position + 1 < statusList.size()) {
+ fetchMoreCallBack.onClick(statusList.get(position + 1).id);
+ }
+ });
}
}
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 0942b6207..e263f3d34 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
@@ -75,6 +75,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
private String max_id, min_id, min_id_fetch_more;
private StatusAdapter statusAdapter;
private Timeline.TimeLineEnum timelineType;
+ private static final int STATUS_PRESENT = -1;
//Handle actions that can be done in other fragments
private final BroadcastReceiver receive_action = new BroadcastReceiver() {
@Override
@@ -179,6 +180,15 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
+ private static final int STATUS_AT_THE_BOTTOM = -2;
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ }
+
+ private ArrayList<String> idOfAddedStatuses;
+
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
@@ -201,6 +211,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
minified = getArguments().getBoolean(Helper.ARG_MINIFIED, false);
statusReport = (Status) getArguments().getSerializable(Helper.ARG_STATUS_REPORT);
}
+ idOfAddedStatuses = new ArrayList<>();
if (tagTimeline != null) {
ident = "@T@" + tagTimeline.name;
if (tagTimeline.isART) {
@@ -234,16 +245,11 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
markers = new ArrayList<>();
max_id = statusReport != null ? statusReport.id : null;
flagLoading = false;
- router(null, false);
+ router(null);
return binding.getRoot();
}
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- }
-
/**
* Intialize the common view for statuses on different timelines
*
@@ -259,9 +265,8 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
binding.swipeContainer.setRefreshing(false);
binding.swipeContainer.setOnRefreshListener(() -> {
binding.swipeContainer.setRefreshing(true);
- max_id = null;
flagLoading = false;
- router(null, false);
+ route(DIRECTION.REFRESH, true);
});
if (statuses == null || statuses.statuses == null || statuses.statuses.size() == 0) {
@@ -289,6 +294,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
statuses.statuses = mediaStatuses;
}
}
+ for (Status status : statuses.statuses) {
+ idOfAddedStatuses.add(status.id);
+ }
flagLoading = statuses.pagination.max_id == null;
binding.recyclerView.setVisibility(View.VISIBLE);
if (statusAdapter != null && this.statuses != null) {
@@ -308,12 +316,11 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (max_id == null || (statuses.pagination.max_id != null && statuses.pagination.max_id.compareTo(max_id) < 0)) {
max_id = statuses.pagination.max_id;
}
- if (min_id == null || (statuses.pagination.max_id != null && statuses.pagination.min_id.compareTo(min_id) > 0)) {
+ if (min_id == null || (statuses.pagination.min_id != null && statuses.pagination.min_id.compareTo(min_id) > 0)) {
min_id = statuses.pagination.min_id;
}
-
statusAdapter = new StatusAdapter(this.statuses, timelineType, minified);
-
+ statusAdapter.fetchMoreCallBack = this;
if (statusReport != null) {
scrollToTop();
}
@@ -340,7 +347,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (!flagLoading) {
flagLoading = true;
binding.loadingNextElements.setVisibility(View.VISIBLE);
- router(DIRECTION.BOTTOM, false);
+ router(DIRECTION.BOTTOM);
}
} else {
binding.loadingNextElements.setVisibility(View.GONE);
@@ -349,7 +356,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (!flagLoading) {
flagLoading = true;
binding.loadingNextElements.setVisibility(View.VISIBLE);
- router(DIRECTION.TOP, false);
+ router(DIRECTION.TOP);
}
}
}
@@ -357,7 +364,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
-
/**
* Update view and pagination when scrolling down
*
@@ -367,10 +373,10 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (binding == null) {
return;
}
+ binding.swipeContainer.setRefreshing(false);
binding.loadingNextElements.setVisibility(View.GONE);
flagLoading = false;
if (statuses != null && fetched_statuses != null && fetched_statuses.statuses != null && fetched_statuses.statuses.size() > 0) {
-
flagLoading = fetched_statuses.pagination.max_id == null;
if (timelineType == Timeline.TimeLineEnum.ART) {
//We have to split media in different statuses
@@ -386,20 +392,11 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
fetched_statuses.statuses = mediaStatuses;
}
- //There are some statuses present in the timeline
- int startId = statuses.size();
- if (direction == DIRECTION.TOP) {
- statuses.addAll(0, fetched_statuses.statuses);
- statusAdapter.notifyItemRangeInserted(0, fetched_statuses.statuses.size());
- //Maybe a better solution but max_id excludes fetched id, so when fetching with min_id we have to scroll top of one status to get it.
- if (fetched_statuses.statuses.size() > 0) {
- binding.recyclerView.scrollToPosition(fetched_statuses.statuses.size() - 1);
- }
- } else {
- statuses.addAll(fetched_statuses.statuses);
- statusAdapter.notifyItemRangeInserted(startId, fetched_statuses.statuses.size());
- }
- if (max_id == null || (fetched_statuses.pagination.max_id != null && fetched_statuses.pagination.max_id.compareTo(max_id) < 0)) {
+ //Update the timeline with new statuses
+ updateStatusListWith(fetched_statuses.statuses, fetchingMissing);
+ if (fetched_statuses.pagination.max_id == null) {
+ flagLoading = true;
+ } else if (max_id == null || fetched_statuses.pagination.max_id.compareTo(max_id) < 0) {
max_id = fetched_statuses.pagination.max_id;
}
if (min_id == null || (fetched_statuses.pagination.min_id != null && fetched_statuses.pagination.min_id.compareTo(min_id) > 0)) {
@@ -410,6 +407,47 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
+ private void updateStatusListWith(List<Status> statusListReceived, boolean fetchingMissing) {
+ if (statusListReceived != null && statusListReceived.size() > 0) {
+ int insertedPosition = STATUS_PRESENT;
+ for (Status statusReceived : statusListReceived) {
+ insertedPosition = insertStatus(statusReceived);
+ }
+ //If there were no overlap for top status
+ if (fetchingMissing && insertedPosition != STATUS_PRESENT && insertedPosition != STATUS_AT_THE_BOTTOM && this.statuses.size() > insertedPosition) {
+ Status statusFetchMore = new Status();
+ statusFetchMore.isFetchMore = true;
+ int insertAt = insertedPosition + 1;
+ this.statuses.add(insertAt, statusFetchMore);
+ statusAdapter.notifyItemInserted(insertAt);
+ }
+ }
+ }
+
+ private int insertStatus(Status statusReceived) {
+ if (idOfAddedStatuses.contains(statusReceived.id)) {
+ return STATUS_PRESENT;
+ }
+ int position = 0;
+ for (Status statusAlreadyPresent : this.statuses) {
+ if (statusAlreadyPresent.created_at != null && statusReceived.created_at != null && statusReceived.created_at.after(statusAlreadyPresent.created_at)) {
+ idOfAddedStatuses.add(statusReceived.id);
+ this.statuses.add(position, statusReceived);
+ statusAdapter.notifyItemInserted(position);
+ break;
+ }
+ position++;
+ }
+ //Statuses added at the bottom, we flag them by position = -2 for not dealing with them and fetch more
+ if (position == this.statuses.size()) {
+ idOfAddedStatuses.add(statusReceived.id);
+ this.statuses.add(position, statusReceived);
+ statusAdapter.notifyItemInserted(position);
+ return STATUS_AT_THE_BOTTOM;
+ }
+ return position;
+ }
+
@Override
public void onPause() {
if (mLayoutManager != null) {
@@ -460,18 +498,18 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
- private void router(DIRECTION direction, boolean fetchingMissing) {
+ private void router(DIRECTION direction) {
if (networkAvailable == BaseMainActivity.status.UNKNOWN) {
new Thread(() -> {
if (networkAvailable == BaseMainActivity.status.UNKNOWN) {
networkAvailable = Helper.isConnectedToInternet(requireActivity(), BaseMainActivity.currentInstance);
}
Handler mainHandler = new Handler(Looper.getMainLooper());
- Runnable myRunnable = () -> route(direction, fetchingMissing);
+ Runnable myRunnable = () -> route(direction, false);
mainHandler.post(myRunnable);
}).start();
} else {
- route(direction, fetchingMissing);
+ route(direction, false);
}
}
@@ -486,7 +524,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (binding == null) {
return;
}
- if (!fetchingMissing && !binding.swipeContainer.isRefreshing() && direction == null && quickLoad != null && quickLoad.statuses != null && quickLoad.statuses.size() > 0) {
+ if (direction != DIRECTION.REFRESH && !fetchingMissing && !binding.swipeContainer.isRefreshing() && direction == null && quickLoad != null && quickLoad.statuses != null && quickLoad.statuses.size() > 0) {
Statuses statuses = new Statuses();
statuses.statuses = quickLoad.statuses;
statuses.pagination = new Pagination();
@@ -515,6 +553,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else if (direction == DIRECTION.TOP) {
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, true, false, false, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
+ } else if (direction == DIRECTION.REFRESH) {
+ timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
+ .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.REFRESH, fetchingMissing));
}
} else if (timelineType == Timeline.TimeLineEnum.PUBLIC) { //PUBLIC TIMELINE
if (direction == null) {
@@ -526,6 +567,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else if (direction == DIRECTION.TOP) {
timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, false, true, false, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
+ } else if (direction == DIRECTION.REFRESH) {
+ timelinesVM.getPublic(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, false, true, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
+ .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.REFRESH, fetchingMissing));
}
} else if (timelineType == Timeline.TimeLineEnum.REMOTE) { //REMOTE TIMELINE
if (direction == null) {
@@ -537,6 +581,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else if (direction == DIRECTION.TOP) {
timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
+ } else if (direction == DIRECTION.REFRESH) {
+ timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
+ .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.REFRESH, fetchingMissing));
}
} else if (timelineType == Timeline.TimeLineEnum.LIST) { //LIST TIMELINE
if (direction == null) {
@@ -548,6 +595,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else if (direction == DIRECTION.TOP) {
timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
+ } else if (direction == DIRECTION.REFRESH) {
+ timelinesVM.getList(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, list_id, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
+ .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.REFRESH, fetchingMissing));
}
} else if (timelineType == Timeline.TimeLineEnum.TAG || timelineType == Timeline.TimeLineEnum.ART) { //TAG TIMELINE
if (tagTimeline == null) {
@@ -563,6 +613,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else if (direction == DIRECTION.TOP) {
timelinesVM.getHashTag(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, tagTimeline.name, false, tagTimeline.isART, tagTimeline.all, tagTimeline.any, tagTimeline.none, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP, fetchingMissing));
+ } else if (direction == DIRECTION.REFRESH) {
+ timelinesVM.getHashTag(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, tagTimeline.name, false, tagTimeline.isART, tagTimeline.all, tagTimeline.any, tagTimeline.none, null, null, null, MastodonHelper.statusesPerCall(requireActivity()))
+ .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.REFRESH, fetchingMissing));
}
} else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_TIMELINE) { //PROFILE TIMELINES
if (direction == null) {
@@ -585,7 +638,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
} else if (direction == DIRECTION.BOTTOM) {
accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, max_id, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity()))
- .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
+ .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
} else {
flagLoading = false;
}
@@ -613,7 +666,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
} else if (direction == DIRECTION.BOTTOM) {
accountsVM.getFavourites(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), null, max_id)
- .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
+ .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
} else {
flagLoading = false;
}
@@ -623,7 +676,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
} else if (direction == DIRECTION.BOTTOM) {
accountsVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), max_id, null, null)
- .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
+ .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
} else {
flagLoading = false;
}
@@ -667,16 +720,16 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else {
max_id = null;
}
- timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
+ timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
});
} else {
- timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
+ timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
}
} else {
- timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, null)
+ timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, null, null)
.observe(getViewLifecycleOwner(), cachedStatus -> {
if (cachedStatus != null && cachedStatus.statuses != null) {
initializeStatusesCommonView(cachedStatus);
@@ -687,35 +740,38 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} else if (direction == DIRECTION.BOTTOM) {
if (networkAvailable == BaseMainActivity.status.CONNECTED) {
//We first if we get results from cache
- timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, max_id, null)
+ timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, max_id, null, null)
.observe(getViewLifecycleOwner(), statusesBottomCache -> {
if (statusesBottomCache != null && statusesBottomCache.statuses != null && statusesBottomCache.statuses.size() > 0) {
dealWithPagination(statusesBottomCache, DIRECTION.BOTTOM, fetchingMissing);
} else { // If not, we fetch remotely
- timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
+ timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchingMissing, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
}
});
} else {
- timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, max_id, null)
+ timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, max_id, null, null)
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, fetchingMissing));
}
} else if (direction == DIRECTION.TOP) {
if (networkAvailable == BaseMainActivity.status.CONNECTED) {
- timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, fetchingMissing ? min_id_fetch_more : min_id)
+ timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, fetchingMissing ? min_id_fetch_more : min_id, null)
.observe(getViewLifecycleOwner(), statusesTopCache -> {
if (statusesTopCache != null && statusesTopCache.statuses != null && statusesTopCache.statuses.size() > 0) {
dealWithPagination(statusesTopCache, DIRECTION.TOP, fetchingMissing);
} else {
- timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()), false)
+ timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchingMissing, null, null, fetchingMissing ? min_id_fetch_more : min_id, MastodonHelper.statusesPerCall(requireActivity()), false)
.observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, fetchingMissing));
}
});
} else {
- timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, fetchingMissing ? min_id_fetch_more : min_id)
+ timelinesVM.getHomeCache(BaseMainActivity.currentInstance, BaseMainActivity.currentUserID, null, fetchingMissing ? min_id_fetch_more : min_id, null)
.observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, fetchingMissing));
}
+ } else if (direction == DIRECTION.REFRESH) {
+ timelinesVM.getHome(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchingMissing, null, null, null, MastodonHelper.statusesPerCall(requireActivity()), false)
+ .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.REFRESH, fetchingMissing));
}
}
@@ -738,6 +794,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
public enum DIRECTION {
TOP,
- BOTTOM
+ BOTTOM,
+ REFRESH
}
} \ No newline at end of file
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 d9716bc80..91e774418 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
@@ -14,6 +14,7 @@ package app.fedilab.android.ui.pageadapter;
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
+import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
@@ -27,6 +28,7 @@ import app.fedilab.android.client.entities.app.Pinned;
import app.fedilab.android.client.entities.app.PinnedTimeline;
import app.fedilab.android.client.entities.app.Timeline;
import app.fedilab.android.helper.Helper;
+import app.fedilab.android.helper.PinnedTimelineHelper;
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonConversation;
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline;
import app.fedilab.android.ui.fragment.timeline.FragmentNotificationContainer;
@@ -37,11 +39,15 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter {
private final Pinned pinned;
private final BottomMenu bottomMenu;
private Fragment mCurrentFragment;
+ private final Context context;
+ private final int toRemove;
- public FedilabPageAdapter(FragmentManager fm, Pinned pinned, BottomMenu bottomMenu) {
+ public FedilabPageAdapter(Context context, FragmentManager fm, Pinned pinned, BottomMenu bottomMenu) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.pinned = pinned;
this.bottomMenu = bottomMenu;
+ this.context = context;
+ toRemove = PinnedTimelineHelper.itemToRemoveInBottomMenu(context);
}
public Fragment getCurrentFragment() {
@@ -68,9 +74,10 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter {
FragmentMastodonTimeline fragment = new FragmentMastodonTimeline();
Bundle bundle = new Bundle();
//Position 3 is for notifications
- if (position < 5) {
+ if (position < BOTTOM_TIMELINE_COUNT - toRemove) {
if (bottomMenu != null) {
BottomMenu.ItemMenuType type = BottomMenu.getType(bottomMenu, position);
+
if (type == null) {
return fragment;
}
@@ -91,7 +98,7 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter {
}
} else {
- int pinnedPosition = position - BOTTOM_TIMELINE_COUNT; //Real position has an offset.
+ int pinnedPosition = position - (BOTTOM_TIMELINE_COUNT - toRemove); //Real position has an offset.
PinnedTimeline pinnedTimeline = pinned.pinnedTimelines.get(pinnedPosition);
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, pinnedTimeline.type);
@@ -112,10 +119,11 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter {
@Override
public int getCount() {
+
if (pinned != null && pinned.pinnedTimelines != null) {
- return pinned.pinnedTimelines.size() + BOTTOM_TIMELINE_COUNT;
+ return pinned.pinnedTimelines.size() + BOTTOM_TIMELINE_COUNT - toRemove;
} else {