Loading app/src/main/java/app/fedilab/android/BaseMainActivity.java +4 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,7 @@ import app.fedilab.android.activities.ReorderTimelinesActivity; import app.fedilab.android.activities.ScheduledActivity; import app.fedilab.android.activities.SearchResultTabActivity; import app.fedilab.android.activities.SettingsActivity; import app.fedilab.android.activities.SuggestionActivity; import app.fedilab.android.activities.TrendsActivity; import app.fedilab.android.broadcastreceiver.NetworkStateReceiver; import app.fedilab.android.client.entities.api.Emoji; Loading Loading @@ -391,6 +392,9 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } else if (id == R.id.nav_trends) { Intent intent = new Intent(this, TrendsActivity.class); startActivity(intent); } else if (id == R.id.nav_suggestions) { Intent intent = new Intent(this, SuggestionActivity.class); startActivity(intent); } else if (id == R.id.nav_cache) { Intent intent = new Intent(BaseMainActivity.this, CacheActivity.class); startActivity(intent); Loading app/src/main/java/app/fedilab/android/activities/SuggestionActivity.java +3 −6 Original line number Diff line number Diff line Loading @@ -23,11 +23,10 @@ import androidx.core.content.ContextCompat; import org.jetbrains.annotations.NotNull; import app.fedilab.android.R; import app.fedilab.android.client.entities.app.Timeline; import app.fedilab.android.databinding.ActivitySuggestionsBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.fragment.timeline.FragmentMastodonAccount; import app.fedilab.android.ui.fragment.timeline.FragmentMastodonSuggestion; public class SuggestionActivity extends BaseActivity { Loading @@ -37,7 +36,7 @@ public class SuggestionActivity extends BaseActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ThemeHelper.applyThemeBar(this); app.fedilab.android.databinding.ActivitySuggestionsBinding binding = ActivitySuggestionsBinding.inflate(getLayoutInflater()); ActivitySuggestionsBinding binding = ActivitySuggestionsBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); Loading @@ -46,9 +45,7 @@ public class SuggestionActivity extends BaseActivity { getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary))); } Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.ACCOUNT_SUGGESTION); Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_tags, new FragmentMastodonAccount(), bundle, null, null); Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_suggestions, new FragmentMastodonSuggestion(), null, null, null); } Loading app/src/main/java/app/fedilab/android/ui/drawer/SuggestionAdapter.java 0 → 100644 +140 −0 Original line number Diff line number Diff line package app.fedilab.android.ui.drawer; /* 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>. */ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.app.ActivityOptionsCompat; import androidx.core.content.ContextCompat; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelStoreOwner; import androidx.recyclerview.widget.RecyclerView; import java.lang.ref.WeakReference; import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.activities.ProfileActivity; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Suggestion; import app.fedilab.android.databinding.DrawerSuggestionBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.viewmodel.mastodon.AccountsVM; public class SuggestionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final List<Suggestion> suggestionList; private Context context; public SuggestionAdapter(List<Suggestion> suggestionList) { this.suggestionList = suggestionList; } public int getCount() { return suggestionList.size(); } public Suggestion getItem(int position) { return suggestionList.get(position); } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { this.context = parent.getContext(); DrawerSuggestionBinding itemBinding = DrawerSuggestionBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new SuggestionViewHolder(itemBinding); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { Account account = suggestionList.get(position).account; SuggestionViewHolder holder = (SuggestionViewHolder) viewHolder; MastodonHelper.loadPPMastodon(holder.binding.avatar, account); AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class); holder.binding.avatar.setOnClickListener(v -> { Intent intent = new Intent(context, ProfileActivity.class); Bundle b = new Bundle(); b.putSerializable(Helper.ARG_ACCOUNT, account); intent.putExtras(b); ActivityOptionsCompat options = ActivityOptionsCompat .makeSceneTransitionAnimation((Activity) context, holder.binding.avatar, context.getString(R.string.activity_porfile_pp)); // start the new activity context.startActivity(intent, options.toBundle()); }); holder.binding.followAction.setIconResource(R.drawable.ic_baseline_person_add_24); holder.binding.followAction.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(context, R.color.cyanea_accent_dark_reference))); holder.binding.displayName.setText( account.getSpanDisplayName(context, new WeakReference<>(holder.binding.displayName)), TextView.BufferType.SPANNABLE); holder.binding.username.setText(String.format("@%s", account.acct)); holder.binding.bio.setText( account.getSpanNote(context, new WeakReference<>(holder.binding.bio)), TextView.BufferType.SPANNABLE); holder.binding.followAction.setEnabled(false); holder.binding.followAction.setOnClickListener(v -> { suggestionList.remove(position); notifyItemRemoved(position); accountsVM.follow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, true, false); }); holder.binding.notInterested.setOnClickListener(view -> { suggestionList.remove(position); notifyItemRemoved(position); accountsVM.removeSuggestion(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id); }); //TODO, remove when supported holder.binding.notInterested.setVisibility(View.GONE); } public long getItemId(int position) { return position; } @Override public int getItemCount() { return suggestionList.size(); } public static class SuggestionViewHolder extends RecyclerView.ViewHolder { DrawerSuggestionBinding binding; SuggestionViewHolder(DrawerSuggestionBinding itemView) { super(itemView.getRoot()); binding = itemView; } } } No newline at end of file app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +0 −8 Original line number Diff line number Diff line Loading @@ -143,14 +143,6 @@ public class FragmentMastodonAccount extends Fragment { accountsVM.getBlocks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), max_id, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } } else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_SUGGESTION) { if (firstLoad) { accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } else { accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } } } Loading app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonSuggestion.java 0 → 100644 +161 −0 Original line number Diff line number Diff line package app.fedilab.android.ui.fragment.timeline; /* 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>. */ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; 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.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Suggestion; import app.fedilab.android.client.entities.api.Suggestions; import app.fedilab.android.databinding.FragmentPaginationBinding; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.SuggestionAdapter; import app.fedilab.android.viewmodel.mastodon.AccountsVM; public class FragmentMastodonSuggestion extends Fragment { private FragmentPaginationBinding binding; private AccountsVM accountsVM; private boolean flagLoading; private List<Suggestion> suggestions; private String max_id; private SuggestionAdapter suggestionAdapter; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { flagLoading = false; binding = FragmentPaginationBinding.inflate(inflater, container, false); binding.getRoot().setBackgroundColor(ThemeHelper.getBackgroundColor(requireActivity())); return binding.getRoot(); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); int c1 = getResources().getColor(R.color.cyanea_accent_reference); binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.cyanea_primary_reference)); binding.swipeContainer.setColorSchemeColors( c1, c1, c1 ); binding.loader.setVisibility(View.VISIBLE); binding.recyclerView.setVisibility(View.GONE); accountsVM = new ViewModelProvider(FragmentMastodonSuggestion.this).get(AccountsVM.class); max_id = null; accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } public void scrollToTop() { binding.recyclerView.setAdapter(suggestionAdapter); } /** * Intialize the view for Suggestions * * @param suggestions {@link Suggestions} */ private void initializeAccountCommonView(final Suggestions suggestions) { flagLoading = false; if (binding == null || !isAdded() || getActivity() == null) { return; } binding.loader.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE); binding.swipeContainer.setRefreshing(false); binding.swipeContainer.setOnRefreshListener(() -> { binding.swipeContainer.setRefreshing(true); flagLoading = false; max_id = null; accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); }); if (suggestions == null || suggestions.suggestions == null || suggestions.suggestions.size() == 0) { binding.noAction.setVisibility(View.VISIBLE); binding.noActionText.setText(R.string.no_accounts); return; } binding.recyclerView.setVisibility(View.VISIBLE); this.suggestions = suggestions.suggestions; suggestionAdapter = new SuggestionAdapter(this.suggestions); flagLoading = suggestions.pagination.max_id == null; LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(suggestionAdapter); max_id = suggestions.pagination.max_id; 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); accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id) .observe(getViewLifecycleOwner(), suggestionsPaginated -> { dealWithPagination(suggestionsPaginated); }); } } else { binding.loadingNextElements.setVisibility(View.GONE); } } } }); } /** * Update view and pagination when scrolling down * * @param suggestions_fetched Suggestions */ private void dealWithPagination(Suggestions suggestions_fetched) { flagLoading = false; if (binding == null || !isAdded() || getActivity() == null) { return; } binding.loadingNextElements.setVisibility(View.GONE); if (this.suggestions != null && suggestions_fetched != null && suggestions_fetched.suggestions != null) { flagLoading = suggestions_fetched.pagination.max_id == null; int startId = this.suggestions.size(); this.suggestions.addAll(suggestions_fetched.suggestions); max_id = suggestions_fetched.pagination.max_id; suggestionAdapter.notifyItemRangeInserted(startId, suggestions_fetched.suggestions.size()); } else { flagLoading = true; } } } No newline at end of file Loading
app/src/main/java/app/fedilab/android/BaseMainActivity.java +4 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,7 @@ import app.fedilab.android.activities.ReorderTimelinesActivity; import app.fedilab.android.activities.ScheduledActivity; import app.fedilab.android.activities.SearchResultTabActivity; import app.fedilab.android.activities.SettingsActivity; import app.fedilab.android.activities.SuggestionActivity; import app.fedilab.android.activities.TrendsActivity; import app.fedilab.android.broadcastreceiver.NetworkStateReceiver; import app.fedilab.android.client.entities.api.Emoji; Loading Loading @@ -391,6 +392,9 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } else if (id == R.id.nav_trends) { Intent intent = new Intent(this, TrendsActivity.class); startActivity(intent); } else if (id == R.id.nav_suggestions) { Intent intent = new Intent(this, SuggestionActivity.class); startActivity(intent); } else if (id == R.id.nav_cache) { Intent intent = new Intent(BaseMainActivity.this, CacheActivity.class); startActivity(intent); Loading
app/src/main/java/app/fedilab/android/activities/SuggestionActivity.java +3 −6 Original line number Diff line number Diff line Loading @@ -23,11 +23,10 @@ import androidx.core.content.ContextCompat; import org.jetbrains.annotations.NotNull; import app.fedilab.android.R; import app.fedilab.android.client.entities.app.Timeline; import app.fedilab.android.databinding.ActivitySuggestionsBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.fragment.timeline.FragmentMastodonAccount; import app.fedilab.android.ui.fragment.timeline.FragmentMastodonSuggestion; public class SuggestionActivity extends BaseActivity { Loading @@ -37,7 +36,7 @@ public class SuggestionActivity extends BaseActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ThemeHelper.applyThemeBar(this); app.fedilab.android.databinding.ActivitySuggestionsBinding binding = ActivitySuggestionsBinding.inflate(getLayoutInflater()); ActivitySuggestionsBinding binding = ActivitySuggestionsBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); Loading @@ -46,9 +45,7 @@ public class SuggestionActivity extends BaseActivity { getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary))); } Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.ACCOUNT_SUGGESTION); Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_tags, new FragmentMastodonAccount(), bundle, null, null); Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_suggestions, new FragmentMastodonSuggestion(), null, null, null); } Loading
app/src/main/java/app/fedilab/android/ui/drawer/SuggestionAdapter.java 0 → 100644 +140 −0 Original line number Diff line number Diff line package app.fedilab.android.ui.drawer; /* 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>. */ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.app.ActivityOptionsCompat; import androidx.core.content.ContextCompat; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelStoreOwner; import androidx.recyclerview.widget.RecyclerView; import java.lang.ref.WeakReference; import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.activities.ProfileActivity; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Suggestion; import app.fedilab.android.databinding.DrawerSuggestionBinding; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.viewmodel.mastodon.AccountsVM; public class SuggestionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final List<Suggestion> suggestionList; private Context context; public SuggestionAdapter(List<Suggestion> suggestionList) { this.suggestionList = suggestionList; } public int getCount() { return suggestionList.size(); } public Suggestion getItem(int position) { return suggestionList.get(position); } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { this.context = parent.getContext(); DrawerSuggestionBinding itemBinding = DrawerSuggestionBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new SuggestionViewHolder(itemBinding); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { Account account = suggestionList.get(position).account; SuggestionViewHolder holder = (SuggestionViewHolder) viewHolder; MastodonHelper.loadPPMastodon(holder.binding.avatar, account); AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class); holder.binding.avatar.setOnClickListener(v -> { Intent intent = new Intent(context, ProfileActivity.class); Bundle b = new Bundle(); b.putSerializable(Helper.ARG_ACCOUNT, account); intent.putExtras(b); ActivityOptionsCompat options = ActivityOptionsCompat .makeSceneTransitionAnimation((Activity) context, holder.binding.avatar, context.getString(R.string.activity_porfile_pp)); // start the new activity context.startActivity(intent, options.toBundle()); }); holder.binding.followAction.setIconResource(R.drawable.ic_baseline_person_add_24); holder.binding.followAction.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(context, R.color.cyanea_accent_dark_reference))); holder.binding.displayName.setText( account.getSpanDisplayName(context, new WeakReference<>(holder.binding.displayName)), TextView.BufferType.SPANNABLE); holder.binding.username.setText(String.format("@%s", account.acct)); holder.binding.bio.setText( account.getSpanNote(context, new WeakReference<>(holder.binding.bio)), TextView.BufferType.SPANNABLE); holder.binding.followAction.setEnabled(false); holder.binding.followAction.setOnClickListener(v -> { suggestionList.remove(position); notifyItemRemoved(position); accountsVM.follow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, true, false); }); holder.binding.notInterested.setOnClickListener(view -> { suggestionList.remove(position); notifyItemRemoved(position); accountsVM.removeSuggestion(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id); }); //TODO, remove when supported holder.binding.notInterested.setVisibility(View.GONE); } public long getItemId(int position) { return position; } @Override public int getItemCount() { return suggestionList.size(); } public static class SuggestionViewHolder extends RecyclerView.ViewHolder { DrawerSuggestionBinding binding; SuggestionViewHolder(DrawerSuggestionBinding itemView) { super(itemView.getRoot()); binding = itemView; } } } No newline at end of file
app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +0 −8 Original line number Diff line number Diff line Loading @@ -143,14 +143,6 @@ public class FragmentMastodonAccount extends Fragment { accountsVM.getBlocks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), max_id, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } } else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_SUGGESTION) { if (firstLoad) { accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } else { accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } } } Loading
app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonSuggestion.java 0 → 100644 +161 −0 Original line number Diff line number Diff line package app.fedilab.android.ui.fragment.timeline; /* 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>. */ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; 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.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Suggestion; import app.fedilab.android.client.entities.api.Suggestions; import app.fedilab.android.databinding.FragmentPaginationBinding; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.SuggestionAdapter; import app.fedilab.android.viewmodel.mastodon.AccountsVM; public class FragmentMastodonSuggestion extends Fragment { private FragmentPaginationBinding binding; private AccountsVM accountsVM; private boolean flagLoading; private List<Suggestion> suggestions; private String max_id; private SuggestionAdapter suggestionAdapter; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { flagLoading = false; binding = FragmentPaginationBinding.inflate(inflater, container, false); binding.getRoot().setBackgroundColor(ThemeHelper.getBackgroundColor(requireActivity())); return binding.getRoot(); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); int c1 = getResources().getColor(R.color.cyanea_accent_reference); binding.swipeContainer.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.cyanea_primary_reference)); binding.swipeContainer.setColorSchemeColors( c1, c1, c1 ); binding.loader.setVisibility(View.VISIBLE); binding.recyclerView.setVisibility(View.GONE); accountsVM = new ViewModelProvider(FragmentMastodonSuggestion.this).get(AccountsVM.class); max_id = null; accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } public void scrollToTop() { binding.recyclerView.setAdapter(suggestionAdapter); } /** * Intialize the view for Suggestions * * @param suggestions {@link Suggestions} */ private void initializeAccountCommonView(final Suggestions suggestions) { flagLoading = false; if (binding == null || !isAdded() || getActivity() == null) { return; } binding.loader.setVisibility(View.GONE); binding.noAction.setVisibility(View.GONE); binding.swipeContainer.setRefreshing(false); binding.swipeContainer.setOnRefreshListener(() -> { binding.swipeContainer.setRefreshing(true); flagLoading = false; max_id = null; accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); }); if (suggestions == null || suggestions.suggestions == null || suggestions.suggestions.size() == 0) { binding.noAction.setVisibility(View.VISIBLE); binding.noActionText.setText(R.string.no_accounts); return; } binding.recyclerView.setVisibility(View.VISIBLE); this.suggestions = suggestions.suggestions; suggestionAdapter = new SuggestionAdapter(this.suggestions); flagLoading = suggestions.pagination.max_id == null; LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(suggestionAdapter); max_id = suggestions.pagination.max_id; 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); accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id) .observe(getViewLifecycleOwner(), suggestionsPaginated -> { dealWithPagination(suggestionsPaginated); }); } } else { binding.loadingNextElements.setVisibility(View.GONE); } } } }); } /** * Update view and pagination when scrolling down * * @param suggestions_fetched Suggestions */ private void dealWithPagination(Suggestions suggestions_fetched) { flagLoading = false; if (binding == null || !isAdded() || getActivity() == null) { return; } binding.loadingNextElements.setVisibility(View.GONE); if (this.suggestions != null && suggestions_fetched != null && suggestions_fetched.suggestions != null) { flagLoading = suggestions_fetched.pagination.max_id == null; int startId = this.suggestions.size(); this.suggestions.addAll(suggestions_fetched.suggestions); max_id = suggestions_fetched.pagination.max_id; suggestionAdapter.notifyItemRangeInserted(startId, suggestions_fetched.suggestions.size()); } else { flagLoading = true; } } } No newline at end of file