Commit 3a200580 authored by Thomas's avatar Thomas
Browse files

Fix #1384 #1386 reverse timeline position and apply to notifications/conversations

parent ae377bb6
Loading
Loading
Loading
Loading
+24 −8
Original line number Diff line number Diff line
@@ -2758,8 +2758,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                holder.binding.fetchMoreContainerTop.setVisibility(View.GONE);
                status.isFetchMore = false;
                status.isFetching = true;
                boolean reverseMode = adapter instanceof StatusAdapter && ((StatusAdapter) adapter).reverseTimeline;
                int position = holder.getBindingAdapterPosition();
                String statusIdMin = null, statusIdMax;
                if (reverseMode) {
                    if (status.positionFetchMore == Status.PositionFetchMore.TOP || position == 0) {
                        statusIdMax = statusList.get(position).id;
                    } else {
                        statusIdMax = statusList.get(position - 1).id;
                    }
                    if (position < statusList.size() - 1) {
                        if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
                            statusIdMin = statusList.get(position + 1).id;
@@ -2767,10 +2774,19 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                            statusIdMin = status.id;
                        }
                    }
                if (status.positionFetchMore == Status.PositionFetchMore.TOP || holder.getBindingAdapterPosition() == 0) {
                    statusIdMax = statusList.get(holder.getBindingAdapterPosition()).id;
                } else {
                    statusIdMax = statusList.get(holder.getBindingAdapterPosition() - 1).id;
                    if (position < statusList.size() - 1) {
                        if (status.positionFetchMore == Status.PositionFetchMore.TOP) {
                            statusIdMin = statusList.get(position + 1).id;
                        } else {
                            statusIdMin = status.id;
                        }
                    }
                    if (status.positionFetchMore == Status.PositionFetchMore.TOP || position == 0) {
                        statusIdMax = statusList.get(position).id;
                    } else {
                        statusIdMax = statusList.get(position - 1).id;
                    }
                }
                fetchMoreCallBack.autoFetch(statusIdMin, statusIdMax, status);
                recyclerView.post(() -> adapter.notifyItemChanged(holder.getBindingAdapterPosition()));
+44 −16
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
    private ConversationAdapter conversationAdapter;
    private LinearLayoutManager mLayoutManager;
    private boolean isViewInitialized;
    private boolean reverseTimeline;
    private Conversations initialConversations;

    //Allow to recreate data when detaching/attaching fragment
@@ -232,7 +233,7 @@ public class FragmentMastodonConversation extends Fragment implements Conversati

    private void storeMarker(BaseAccount connectedAccount) {
        if (mLayoutManager != null) {
            int position = mLayoutManager.findFirstVisibleItemPosition();
            int position = reverseTimeline ? mLayoutManager.findLastVisibleItemPosition() : mLayoutManager.findFirstVisibleItemPosition();
            if (conversationList != null && conversationList.size() > position) {
                try {
                    Conversation conversation = conversationList.get(position);
@@ -312,9 +313,14 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
            min_id = conversations.pagination.min_id;
        }

        SharedPreferences sharedpref = PreferenceManager.getDefaultSharedPreferences(requireActivity());
        reverseTimeline = sharedpref.getBoolean(getString(R.string.SET_REVERSE_TIMELINE), false);
        conversationAdapter = new ConversationAdapter(conversationList);
        conversationAdapter.fetchMoreCallBack = this;
        mLayoutManager = new LinearLayoutManager(requireActivity());
        if (reverseTimeline) {
            mLayoutManager.setReverseLayout(true);
        }
        binding.recyclerView.setLayoutManager(mLayoutManager);
        binding.recyclerView.setAdapter(conversationAdapter);

@@ -322,16 +328,37 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                if (requireActivity() instanceof BaseMainActivity) {
                    if (dy < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility())
                    int dyDirection = reverseTimeline ? -dy : dy;
                    if (dyDirection < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility())
                        ((BaseMainActivity) requireActivity()).manageFloatingButton(true);
                    if (dy > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility())
                    if (dyDirection > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility())
                        ((BaseMainActivity) requireActivity()).manageFloatingButton(false);
                }
                int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
                if (reverseTimeline) {
                    if (dy < 0) {
                        int visibleItemCount = mLayoutManager.getChildCount();
                        int totalItemCount = mLayoutManager.getItemCount();
                        if (firstVisibleItem + visibleItemCount == totalItemCount) {
                            if (!flagLoading) {
                                flagLoading = true;
                                binding.loadingNextElements.setVisibility(View.VISIBLE);
                                route(FragmentMastodonTimeline.DIRECTION.BOTTOM, false);
                            }
                        } else {
                            binding.loadingNextElements.setVisibility(View.GONE);
                        }
                    } else if (firstVisibleItem == 0) {
                        if (!flagLoading) {
                            flagLoading = true;
                            binding.loadingNextElements.setVisibility(View.VISIBLE);
                            route(FragmentMastodonTimeline.DIRECTION.TOP, false);
                        }
                    }
                } else {
                    if (dy > 0) {
                        int visibleItemCount = mLayoutManager.getChildCount();
                        int totalItemCount = mLayoutManager.getItemCount();

                        if (firstVisibleItem + visibleItemCount == totalItemCount) {
                            if (!flagLoading) {
                                flagLoading = true;
@@ -341,7 +368,7 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
                        } else {
                            binding.loadingNextElements.setVisibility(View.GONE);
                        }
                } else if (firstVisibleItem == 0) { //Scroll top and item is zero
                    } else if (firstVisibleItem == 0) {
                        if (!flagLoading) {
                            flagLoading = true;
                            binding.loadingNextElements.setVisibility(View.VISIBLE);
@@ -349,6 +376,7 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
                        }
                    }
                }
            }
        });

    }
+44 −16
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
    private NotificationTypeEnum notificationType;
    private boolean aggregateNotification;
    private boolean groupedByServer;
    private boolean reverseTimeline;

    private final BroadcastReceiver receive_refresh = new BroadcastReceiver() {

@@ -326,25 +327,51 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
            min_id = notifications.pagination.min_id;
        }

        SharedPreferences sharedpref = PreferenceManager.getDefaultSharedPreferences(requireActivity());
        reverseTimeline = sharedpref.getBoolean(getString(R.string.SET_REVERSE_TIMELINE), false);
        notificationAdapter = new NotificationAdapter(notificationList);
        notificationAdapter.fetchMoreCallBack = this;
        mLayoutManager = new LinearLayoutManager(requireActivity());
        if (reverseTimeline) {
            mLayoutManager.setReverseLayout(true);
        }
        binding.recyclerView.setLayoutManager(mLayoutManager);
        binding.recyclerView.setAdapter(notificationAdapter);
        binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                if (requireActivity() instanceof BaseMainActivity) {
                    if (dy < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility())
                    int dyDirection = reverseTimeline ? -dy : dy;
                    if (dyDirection < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility())
                        ((BaseMainActivity) requireActivity()).manageFloatingButton(true);
                    if (dy > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility())
                    if (dyDirection > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility())
                        ((BaseMainActivity) requireActivity()).manageFloatingButton(false);
                }
                int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
                if (reverseTimeline) {
                    if (dy < 0) {
                        int visibleItemCount = mLayoutManager.getChildCount();
                        int totalItemCount = mLayoutManager.getItemCount();
                        if (firstVisibleItem + visibleItemCount == totalItemCount) {
                            if (!flagLoading) {
                                flagLoading = true;
                                binding.loadingNextElements.setVisibility(View.VISIBLE);
                                route(FragmentMastodonTimeline.DIRECTION.BOTTOM, false);
                            }
                        } else {
                            binding.loadingNextElements.setVisibility(View.GONE);
                        }
                    } else if (firstVisibleItem == 0) {
                        if (!flagLoading) {
                            flagLoading = true;
                            binding.loadingNextElements.setVisibility(View.VISIBLE);
                            route(FragmentMastodonTimeline.DIRECTION.TOP, false);
                        }
                    }
                } else {
                    if (dy > 0) {
                        int visibleItemCount = mLayoutManager.getChildCount();
                        int totalItemCount = mLayoutManager.getItemCount();

                        if (firstVisibleItem + visibleItemCount == totalItemCount) {
                            if (!flagLoading) {
                                flagLoading = true;
@@ -354,7 +381,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
                        } else {
                            binding.loadingNextElements.setVisibility(View.GONE);
                        }
                } else if (firstVisibleItem == 0) { //Scroll top and item is zero
                    } else if (firstVisibleItem == 0) {
                        if (!flagLoading) {
                            flagLoading = true;
                            binding.loadingNextElements.setVisibility(View.VISIBLE);
@@ -362,6 +389,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
                        }
                    }
                }
            }
        });
    }

@@ -624,7 +652,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati

    private void storeMarker(BaseAccount connectedAccount) {
        if (mLayoutManager != null) {
            int position = mLayoutManager.findFirstVisibleItemPosition();
            int position = reverseTimeline ? mLayoutManager.findLastVisibleItemPosition() : mLayoutManager.findFirstVisibleItemPosition();
            if (notificationList != null && notificationList.size() > position) {
                try {
                    if (notificationType == NotificationTypeEnum.ALL) {
+20 −5
Original line number Diff line number Diff line
@@ -601,7 +601,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                timelineStatuses.addAll(fetched_statuses.statuses);
                statusAdapter.notifyItemRangeInserted(fromPosition, insertedStatus);
            } else if (timelineType == Timeline.TimeLineEnum.ART) {
                if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP || direction == DIRECTION.FETCH_NEW) {
                if (direction == DIRECTION.REFRESH || direction == DIRECTION.SCROLL_TOP) {
                    // Clear and rebuild with fresh content
                    int previousSize = timelineStatuses.size();
                    timelineStatuses.clear();
@@ -609,7 +609,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                    timelineStatuses.addAll(fetched_statuses.statuses);
                    insertedStatus = fetched_statuses.statuses.size();
                    statusAdapter.notifyItemRangeInserted(0, insertedStatus);
                } else if (direction == DIRECTION.TOP) {
                } else if (direction == DIRECTION.TOP || direction == DIRECTION.FETCH_NEW) {
                    // Prepend new statuses with dedup based on status id + attachment id
                    List<Status> toAdd = new ArrayList<>();
                    for (Status newStatus : fetched_statuses.statuses) {
@@ -804,7 +804,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
        mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        if (reverseTimeline) {
            mLayoutManager.setReverseLayout(true);
            mLayoutManager.setStackFromEnd(true);
        }
        binding.recyclerView.setLayoutManager(mLayoutManager);
        binding.recyclerView.setAdapter(statusAdapter);
@@ -822,9 +821,10 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    scrollingUp = dy < 0;
                    if (requireActivity() instanceof BaseMainActivity) {
                        if (dy < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility())
                        int dyDirection = reverseTimeline ? -dy : dy;
                        if (dyDirection < 0 && !((BaseMainActivity) requireActivity()).getFloatingVisibility())
                            ((BaseMainActivity) requireActivity()).manageFloatingButton(true);
                        if (dy > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility())
                        if (dyDirection > 0 && ((BaseMainActivity) requireActivity()).getFloatingVisibility())
                            ((BaseMainActivity) requireActivity()).manageFloatingButton(false);
                    }
                    int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
@@ -1529,6 +1529,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                } else if (direction == DIRECTION.BOTTOM) {
                    misskeyTimelinesVM.getUserReactions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, userId, max_id, null, limit)
                            .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false, true, fetchStatus));
                } else if (direction == DIRECTION.TOP) {
                    misskeyTimelinesVM.getUserReactions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, userId, null, min_id, limit)
                            .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false, true, fetchStatus));
                } else {
                    flagLoading = false;
                }
@@ -1539,6 +1542,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                } 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, false, true, fetchStatus));
                } else if (direction == DIRECTION.TOP) {
                    accountsVM.getFavourites(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), min_id, null)
                            .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false, true, fetchStatus));
                } else {
                    flagLoading = false;
                }
@@ -1553,6 +1559,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                } else if (direction == DIRECTION.BOTTOM) {
                    misskeyTimelinesVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id, null, limit)
                            .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false, true, fetchStatus));
                } else if (direction == DIRECTION.TOP) {
                    misskeyTimelinesVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null, min_id, limit)
                            .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false, true, fetchStatus));
                } else {
                    flagLoading = false;
                }
@@ -1563,6 +1572,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
                } 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, false, true, fetchStatus));
                } else if (direction == DIRECTION.TOP) {
                    accountsVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), null, null, min_id)
                            .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false, true, fetchStatus));
                } else {
                    flagLoading = false;
                }
@@ -1651,6 +1663,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
        } else if (direction == DIRECTION.BOTTOM) {
            accountsVM.getAccountStatuses(tempInstance, tempToken, accountId, max_id, null, null, exclude_replies, exclude_reblogs, media_only, false, tagged, MastodonHelper.statusesPerCall(requireActivity()))
                    .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false, true, fetchStatus));
        } else if (direction == DIRECTION.TOP) {
            accountsVM.getAccountStatuses(tempInstance, tempToken, accountId, null, null, min_id, exclude_replies, exclude_reblogs, media_only, false, tagged, MastodonHelper.statusesPerCall(requireActivity()))
                    .observe(getViewLifecycleOwner(), statusesTop -> dealWithPagination(statusesTop, DIRECTION.TOP, false, true, fetchStatus));
        } else {
            flagLoading = false;
        }