Loading app/src/main/java/app/fedilab/android/client/entities/api/Pagination.java +1 −0 Original line number Diff line number Diff line Loading @@ -19,4 +19,5 @@ public class Pagination { public String max_id; public String min_id; public String since_id; public Integer offset; } app/src/main/java/app/fedilab/android/client/entities/api/Results.java +1 −0 Original line number Diff line number Diff line Loading @@ -24,5 +24,6 @@ public class Results { public java.util.List<Status> statuses; @SerializedName("hashtags") public java.util.List<Tag> hashtags; public Pagination pagination; } app/src/main/java/app/fedilab/android/helper/MastodonHelper.java +1 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ public class MastodonHelper { public static final int ACCOUNTS_PER_CALL = 40; public static final int STATUSES_PER_CALL = 40; public static final int SEARCH_PER_CALL = 20; public static final int NOTIFICATIONS_PER_CALL = 30; Loading app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +35 −13 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ public class FragmentMastodonAccount extends Fragment { private boolean flagLoading; private List<Account> accounts; private String max_id; private Integer offset; private AccountAdapter accountAdapter; private String search; private Account accountTimeline; Loading Loading @@ -84,6 +85,7 @@ public class FragmentMastodonAccount extends Fragment { binding.recyclerView.setVisibility(View.GONE); accountsVM = new ViewModelProvider(FragmentMastodonAccount.this).get(viewModelKey, AccountsVM.class); max_id = null; offset = 0; router(true); } Loading @@ -109,7 +111,8 @@ public class FragmentMastodonAccount extends Fragment { } } else if (search != null) { SearchVM searchVM = new ViewModelProvider(FragmentMastodonAccount.this).get(viewModelKey, SearchVM.class); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "accounts", false, true, false, 0, null, null, MastodonHelper.STATUSES_PER_CALL) if (firstLoad) { searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "accounts", false, true, false, 0, null, null, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), results -> { if (results != null) { Accounts accounts = new Accounts(); Loading @@ -121,6 +124,18 @@ public class FragmentMastodonAccount extends Fragment { Toasty.error(requireActivity(), getString(R.string.toast_error), Toasty.LENGTH_SHORT).show(); } }); } else { searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "accounts", false, true, false, offset, null, null, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), results -> { if (results != null) { Accounts accounts = new Accounts(); Pagination pagination = new Pagination(); accounts.accounts = results.accounts; accounts.pagination = pagination; dealWithPagination(accounts); } }); } } else if (timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE) { if (firstLoad) { accountsVM.getMutes(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), null, null) Loading Loading @@ -204,7 +219,11 @@ public class FragmentMastodonAccount extends Fragment { this.accounts = accounts.accounts; accountAdapter = new AccountAdapter(this.accounts, timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE_HOME); if (search == null) { flagLoading = accounts.pagination.max_id == null; } else { offset += MastodonHelper.SEARCH_PER_CALL; } LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(accountAdapter); Loading Loading @@ -263,6 +282,9 @@ public class FragmentMastodonAccount extends Fragment { //Fetch the relationship fetchRelationShip(fetched_accounts.accounts, position); max_id = fetched_accounts.pagination.max_id; if (search != null) { offset += MastodonHelper.SEARCH_PER_CALL; } accountAdapter.notifyItemRangeInserted(startId, fetched_accounts.accounts.size()); } else { flagLoading = true; Loading app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTag.java +63 −5 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.Collections; Loading @@ -49,6 +50,9 @@ public class FragmentMastodonTag extends Fragment { private TagAdapter tagAdapter; private String search; private Timeline.TimeLineEnum timelineType; private Integer offset; private boolean flagLoading; private List<Tag> tagList; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Loading @@ -66,6 +70,10 @@ public class FragmentMastodonTag extends Fragment { super.onViewCreated(view, savedInstanceState); binding.loader.setVisibility(View.VISIBLE); binding.recyclerView.setVisibility(View.GONE); offset = 0; flagLoading = false; binding.swipeContainer.setRefreshing(false); binding.swipeContainer.setEnabled(false); router(); } Loading @@ -75,16 +83,24 @@ public class FragmentMastodonTag extends Fragment { private void router() { if (search != null && timelineType == null) { SearchVM searchVM = new ViewModelProvider(FragmentMastodonTag.this).get(SearchVM.class); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "hashtags", false, true, false, 0, null, null, MastodonHelper.STATUSES_PER_CALL) searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "hashtags", false, true, false, offset, null, null, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), results -> { if (results != null && results.hashtags != null) { if (results != null && results.hashtags != null && offset == 0) { initializeTagCommonView(results.hashtags); } else if (results != null && results.hashtags != null) { dealWithPaginationTag(results.hashtags); } }); } else if (timelineType == Timeline.TimeLineEnum.TREND_TAG) { TimelinesVM timelinesVM = new ViewModelProvider(FragmentMastodonTag.this).get(TimelinesVM.class); timelinesVM.getTagsTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance) .observe(getViewLifecycleOwner(), this::initializeTagCommonView); timelinesVM.getTagsTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, offset, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), tags -> { if (tags != null && offset == 0) { initializeTagCommonView(tags); } else if (tags != null) { dealWithPaginationTag(tags); } }); } } Loading @@ -92,6 +108,24 @@ public class FragmentMastodonTag extends Fragment { binding.recyclerView.setAdapter(tagAdapter); } private void dealWithPaginationTag(final List<Tag> tags) { if (binding == null || !isAdded() || getActivity() == null) { return; } if (tags == null || tags.size() == 0) { flagLoading = true; binding.loadingNextElements.setVisibility(View.GONE); return; } offset += MastodonHelper.SEARCH_PER_CALL; binding.swipeContainer.setRefreshing(false); binding.loadingNextElements.setVisibility(View.GONE); flagLoading = false; int start = tagList.size(); tagList.addAll(tags); tagAdapter.notifyItemRangeInserted(start, tags.size()); } /** * Intialize the view for tags * Loading @@ -101,6 +135,7 @@ public class FragmentMastodonTag extends Fragment { if (binding == null || !isAdded() || getActivity() == null) { return; } tagList = new ArrayList<>(); binding.loader.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE); binding.swipeContainer.setRefreshing(false); Loading Loading @@ -130,12 +165,35 @@ public class FragmentMastodonTag extends Fragment { tags.add(0, tag); } } offset += MastodonHelper.SEARCH_PER_CALL; binding.recyclerView.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.GONE); tagAdapter = new TagAdapter(tags); tagList.addAll(tags); tagAdapter = new TagAdapter(tagList); LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(tagAdapter); binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); if (dy > 0) { int visibleItemCount = mLayoutManager.getChildCount(); int totalItemCount = mLayoutManager.getItemCount(); if (firstVisibleItem + visibleItemCount == totalItemCount) { if (!flagLoading) { flagLoading = true; binding.loadingNextElements.setVisibility(View.VISIBLE); router(); } } else { binding.loadingNextElements.setVisibility(View.GONE); } } } }); } } No newline at end of file Loading
app/src/main/java/app/fedilab/android/client/entities/api/Pagination.java +1 −0 Original line number Diff line number Diff line Loading @@ -19,4 +19,5 @@ public class Pagination { public String max_id; public String min_id; public String since_id; public Integer offset; }
app/src/main/java/app/fedilab/android/client/entities/api/Results.java +1 −0 Original line number Diff line number Diff line Loading @@ -24,5 +24,6 @@ public class Results { public java.util.List<Status> statuses; @SerializedName("hashtags") public java.util.List<Tag> hashtags; public Pagination pagination; }
app/src/main/java/app/fedilab/android/helper/MastodonHelper.java +1 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ public class MastodonHelper { public static final int ACCOUNTS_PER_CALL = 40; public static final int STATUSES_PER_CALL = 40; public static final int SEARCH_PER_CALL = 20; public static final int NOTIFICATIONS_PER_CALL = 30; Loading
app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +35 −13 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ public class FragmentMastodonAccount extends Fragment { private boolean flagLoading; private List<Account> accounts; private String max_id; private Integer offset; private AccountAdapter accountAdapter; private String search; private Account accountTimeline; Loading Loading @@ -84,6 +85,7 @@ public class FragmentMastodonAccount extends Fragment { binding.recyclerView.setVisibility(View.GONE); accountsVM = new ViewModelProvider(FragmentMastodonAccount.this).get(viewModelKey, AccountsVM.class); max_id = null; offset = 0; router(true); } Loading @@ -109,7 +111,8 @@ public class FragmentMastodonAccount extends Fragment { } } else if (search != null) { SearchVM searchVM = new ViewModelProvider(FragmentMastodonAccount.this).get(viewModelKey, SearchVM.class); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "accounts", false, true, false, 0, null, null, MastodonHelper.STATUSES_PER_CALL) if (firstLoad) { searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "accounts", false, true, false, 0, null, null, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), results -> { if (results != null) { Accounts accounts = new Accounts(); Loading @@ -121,6 +124,18 @@ public class FragmentMastodonAccount extends Fragment { Toasty.error(requireActivity(), getString(R.string.toast_error), Toasty.LENGTH_SHORT).show(); } }); } else { searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "accounts", false, true, false, offset, null, null, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), results -> { if (results != null) { Accounts accounts = new Accounts(); Pagination pagination = new Pagination(); accounts.accounts = results.accounts; accounts.pagination = pagination; dealWithPagination(accounts); } }); } } else if (timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE) { if (firstLoad) { accountsVM.getMutes(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), null, null) Loading Loading @@ -204,7 +219,11 @@ public class FragmentMastodonAccount extends Fragment { this.accounts = accounts.accounts; accountAdapter = new AccountAdapter(this.accounts, timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE_HOME); if (search == null) { flagLoading = accounts.pagination.max_id == null; } else { offset += MastodonHelper.SEARCH_PER_CALL; } LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(accountAdapter); Loading Loading @@ -263,6 +282,9 @@ public class FragmentMastodonAccount extends Fragment { //Fetch the relationship fetchRelationShip(fetched_accounts.accounts, position); max_id = fetched_accounts.pagination.max_id; if (search != null) { offset += MastodonHelper.SEARCH_PER_CALL; } accountAdapter.notifyItemRangeInserted(startId, fetched_accounts.accounts.size()); } else { flagLoading = true; Loading
app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTag.java +63 −5 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.Collections; Loading @@ -49,6 +50,9 @@ public class FragmentMastodonTag extends Fragment { private TagAdapter tagAdapter; private String search; private Timeline.TimeLineEnum timelineType; private Integer offset; private boolean flagLoading; private List<Tag> tagList; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Loading @@ -66,6 +70,10 @@ public class FragmentMastodonTag extends Fragment { super.onViewCreated(view, savedInstanceState); binding.loader.setVisibility(View.VISIBLE); binding.recyclerView.setVisibility(View.GONE); offset = 0; flagLoading = false; binding.swipeContainer.setRefreshing(false); binding.swipeContainer.setEnabled(false); router(); } Loading @@ -75,16 +83,24 @@ public class FragmentMastodonTag extends Fragment { private void router() { if (search != null && timelineType == null) { SearchVM searchVM = new ViewModelProvider(FragmentMastodonTag.this).get(SearchVM.class); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "hashtags", false, true, false, 0, null, null, MastodonHelper.STATUSES_PER_CALL) searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, search.trim(), null, "hashtags", false, true, false, offset, null, null, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), results -> { if (results != null && results.hashtags != null) { if (results != null && results.hashtags != null && offset == 0) { initializeTagCommonView(results.hashtags); } else if (results != null && results.hashtags != null) { dealWithPaginationTag(results.hashtags); } }); } else if (timelineType == Timeline.TimeLineEnum.TREND_TAG) { TimelinesVM timelinesVM = new ViewModelProvider(FragmentMastodonTag.this).get(TimelinesVM.class); timelinesVM.getTagsTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance) .observe(getViewLifecycleOwner(), this::initializeTagCommonView); timelinesVM.getTagsTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, offset, MastodonHelper.SEARCH_PER_CALL) .observe(getViewLifecycleOwner(), tags -> { if (tags != null && offset == 0) { initializeTagCommonView(tags); } else if (tags != null) { dealWithPaginationTag(tags); } }); } } Loading @@ -92,6 +108,24 @@ public class FragmentMastodonTag extends Fragment { binding.recyclerView.setAdapter(tagAdapter); } private void dealWithPaginationTag(final List<Tag> tags) { if (binding == null || !isAdded() || getActivity() == null) { return; } if (tags == null || tags.size() == 0) { flagLoading = true; binding.loadingNextElements.setVisibility(View.GONE); return; } offset += MastodonHelper.SEARCH_PER_CALL; binding.swipeContainer.setRefreshing(false); binding.loadingNextElements.setVisibility(View.GONE); flagLoading = false; int start = tagList.size(); tagList.addAll(tags); tagAdapter.notifyItemRangeInserted(start, tags.size()); } /** * Intialize the view for tags * Loading @@ -101,6 +135,7 @@ public class FragmentMastodonTag extends Fragment { if (binding == null || !isAdded() || getActivity() == null) { return; } tagList = new ArrayList<>(); binding.loader.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE); binding.swipeContainer.setRefreshing(false); Loading Loading @@ -130,12 +165,35 @@ public class FragmentMastodonTag extends Fragment { tags.add(0, tag); } } offset += MastodonHelper.SEARCH_PER_CALL; binding.recyclerView.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.GONE); tagAdapter = new TagAdapter(tags); tagList.addAll(tags); tagAdapter = new TagAdapter(tagList); LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(tagAdapter); binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); if (dy > 0) { int visibleItemCount = mLayoutManager.getChildCount(); int totalItemCount = mLayoutManager.getItemCount(); if (firstVisibleItem + visibleItemCount == totalItemCount) { if (!flagLoading) { flagLoading = true; binding.loadingNextElements.setVisibility(View.VISIBLE); router(); } } else { binding.loadingNextElements.setVisibility(View.GONE); } } } }); } } No newline at end of file