From d5a5f0872798fcd7e58e57c10b21549736e9b86d Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 12 Jan 2023 14:35:44 +0100 Subject: [PATCH] Instance directory --- app/src/main/AndroidManifest.xml | 5 ++ .../app/fedilab/android/BaseMainActivity.java | 4 + .../android/activities/DirectoryActivity.java | 83 +++++++++++++++++++ .../endpoints/MastodonAccountsService.java | 11 +++ .../android/client/entities/app/Timeline.java | 2 + .../app/fedilab/android/helper/Helper.java | 2 + .../timeline/FragmentMastodonAccount.java | 20 ++++- .../viewmodel/mastodon/AccountsVM.java | 33 +++++++- .../ic_baseline_perm_contact_calendar_24.xml | 10 +++ .../main/res/layout/activity_directory.xml | 31 +++++++ .../main/res/menu/activity_main_drawer.xml | 5 ++ app/src/main/res/menu/menu_directory.xml | 23 +++++ app/src/main/res/values/strings.xml | 2 + .../metadata/android/en/changelogs/464.txt | 1 + 14 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/app/fedilab/android/activities/DirectoryActivity.java create mode 100644 app/src/main/res/drawable/ic_baseline_perm_contact_calendar_24.xml create mode 100644 app/src/main/res/layout/activity_directory.xml create mode 100644 app/src/main/res/menu/menu_directory.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6543017c..61a0d0a4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -249,6 +249,11 @@ android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/Suggestions" android:theme="@style/AppThemeBar" /> + . */ + +import static app.fedilab.android.client.entities.app.Timeline.TimeLineEnum.ACCOUNT_DIRECTORY; + +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; + +import org.jetbrains.annotations.NotNull; + +import app.fedilab.android.R; +import app.fedilab.android.databinding.ActivityDirectoryBinding; +import app.fedilab.android.helper.Helper; +import app.fedilab.android.ui.fragment.timeline.FragmentMastodonAccount; + + +public class DirectoryActivity extends BaseBarActivity { + + private static boolean local = false; + private static String order = "active"; + private FragmentMastodonAccount fragmentMastodonAccount; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ActivityDirectoryBinding binding = ActivityDirectoryBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + fragmentMastodonAccount = new FragmentMastodonAccount(); + Bundle bundle = new Bundle(); + bundle.putBoolean(Helper.ARG_DIRECTORY_LOCAL, local); + bundle.putString(Helper.ARG_DIRECTORY_ORDER, order); + bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, ACCOUNT_DIRECTORY); + Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_directory, fragmentMastodonAccount, bundle, null, null); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_directory, menu); + if (order.equals("active")) { + menu.findItem(R.id.order_active).setChecked(true); + } else { + menu.findItem(R.id.order_new).setChecked(true); + } + menu.findItem(R.id.action_local).setChecked(local); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NotNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } else if (item.getItemId() == R.id.action_local) { + item.setChecked(!item.isChecked()); + local = item.isChecked(); + } else if (item.getItemId() == R.id.order_active) { + order = "active"; + } else if (item.getItemId() == R.id.order_new) { + order = "new"; + } + recreate(); + return super.onOptionsItemSelected(item); + } + +} diff --git a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java index 28b10231..b7cba899 100644 --- a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java +++ b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java @@ -417,4 +417,15 @@ public interface MastodonAccountsService { @Header("Authorization") String token, @Path("account_id") String account_id ); + + + //Get user suggestions + @GET("directory") + Call> getDirectory( + @Header("Authorization") String token, + @Query("offset") Integer offset, + @Query("limit") Integer limit, + @Query("order") String order, + @Query("local") Boolean local + ); } diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java b/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java index e3c5fa66..c4196055 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java @@ -382,6 +382,8 @@ public class Timeline { TREND_MESSAGE("TREND_MESSAGE"), @SerializedName("ACCOUNT_SUGGESTION") ACCOUNT_SUGGESTION("ACCOUNT_SUGGESTION"), + @SerializedName("ACCOUNT_DIRECTORY") + ACCOUNT_DIRECTORY("ACCOUNT_DIRECTORY"), @SerializedName("PUBLIC_TREND_MESSAGE") TREND_MESSAGE_PUBLIC("TREND_MESSAGE_PUBLIC"), @SerializedName("STATUS_HISTORY") diff --git a/app/src/main/java/app/fedilab/android/helper/Helper.java b/app/src/main/java/app/fedilab/android/helper/Helper.java index 2d31e605..23fd97a3 100644 --- a/app/src/main/java/app/fedilab/android/helper/Helper.java +++ b/app/src/main/java/app/fedilab/android/helper/Helper.java @@ -253,6 +253,8 @@ public class Helper { public static final String ARG_WORK_ID = "ARG_WORK_ID"; public static final String ARG_LIST_ID = "ARG_LIST_ID"; public static final String ARG_SEARCH_KEYWORD = "ARG_SEARCH_KEYWORD"; + public static final String ARG_DIRECTORY_ORDER = "ARG_DIRECTORY_ORDER"; + public static final String ARG_DIRECTORY_LOCAL = "ARG_DIRECTORY_LOCAL"; public static final String ARG_SEARCH_TYPE = "ARG_SEARCH_TYPE"; public static final String ARG_SEARCH_KEYWORD_CACHE = "ARG_SEARCH_KEYWORD_CACHE"; public static final String ARG_VIEW_MODEL_KEY = "ARG_VIEW_MODEL_KEY"; diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java index b71ef24c..e8270311 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java @@ -15,6 +15,8 @@ package app.fedilab.android.ui.fragment.timeline; * see . */ +import static app.fedilab.android.helper.MastodonHelper.ACCOUNTS_PER_CALL; + import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -63,6 +65,8 @@ public class FragmentMastodonAccount extends Fragment { private FedilabProfileTLPageAdapter.follow_type followType; private String viewModelKey; private Timeline.TimeLineEnum timelineType; + private String order; + private Boolean local; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -72,6 +76,8 @@ public class FragmentMastodonAccount extends Fragment { followType = (FedilabProfileTLPageAdapter.follow_type) getArguments().getSerializable(Helper.ARG_FOLLOW_TYPE); viewModelKey = getArguments().getString(Helper.ARG_VIEW_MODEL_KEY, ""); timelineType = (Timeline.TimeLineEnum) getArguments().get(Helper.ARG_TIMELINE_TYPE); + order = getArguments().getString(Helper.ARG_DIRECTORY_ORDER, "active"); + local = getArguments().getBoolean(Helper.ARG_DIRECTORY_LOCAL, false); } flagLoading = false; binding = FragmentPaginationBinding.inflate(inflater, container, false); @@ -159,7 +165,15 @@ public class FragmentMastodonAccount extends Fragment { .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } else { accountsVM.getBlocks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), max_id, null) + .observe(getViewLifecycleOwner(), this::dealWithPagination); + } + } else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_DIRECTORY) { + if (firstLoad) { + accountsVM.getDirectory(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, 0, ACCOUNTS_PER_CALL, order, local) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); + } else { + accountsVM.getDirectory(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, offset, ACCOUNTS_PER_CALL, order, local) + .observe(getViewLifecycleOwner(), this::dealWithPagination); } } } @@ -223,8 +237,10 @@ public class FragmentMastodonAccount extends Fragment { this.accounts = accounts.accounts; accountAdapter = new AccountAdapter(this.accounts, timelineType == Timeline.TimeLineEnum.MUTED_TIMELINE_HOME); - if (search == null) { + if (search == null && timelineType != Timeline.TimeLineEnum.ACCOUNT_DIRECTORY) { flagLoading = accounts.pagination.max_id == null; + } else if (timelineType != Timeline.TimeLineEnum.ACCOUNT_DIRECTORY) { + offset += ACCOUNTS_PER_CALL; } else { offset += MastodonHelper.SEARCH_PER_CALL; } @@ -288,6 +304,8 @@ public class FragmentMastodonAccount extends Fragment { max_id = fetched_accounts.pagination.max_id; if (search != null) { offset += MastodonHelper.SEARCH_PER_CALL; + } else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_DIRECTORY) { + offset += ACCOUNTS_PER_CALL; } accountAdapter.notifyItemRangeInserted(startId, fetched_accounts.accounts.size()); } else { diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index e9f23ec1..1567a502 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -1595,7 +1595,7 @@ public class AccountsVM extends AndroidViewModel { * Accounts the user has had past positive interactions with, but is not yet following. * * @param limit Maximum number of results to return. Defaults to 40. - * @return {@link LiveData} containing a {@link List} of {@link Account}s + * @return {@link LiveData} containing a {@link List} of {@link Suggestion}s */ public LiveData getSuggestions(@NonNull String instance, String token, String limit) { suggestionsMutableLiveData = new MutableLiveData<>(); @@ -1621,6 +1621,37 @@ public class AccountsVM extends AndroidViewModel { return suggestionsMutableLiveData; } + /** + * List accounts visible in the directory. + * + * @param limit Maximum number of results to return. Defaults to 40. + * @return {@link LiveData} containing a {@link List} of {@link Account}s + */ + public LiveData getDirectory(@NonNull String instance, String token, Integer offset, Integer limit, String order, Boolean local) { + accountsMutableLiveData = new MutableLiveData<>(); + MastodonAccountsService mastodonAccountsService = init(instance); + new Thread(() -> { + Call> accountsCall = mastodonAccountsService.getDirectory(token, offset, limit, order, local); + Accounts accounts = new Accounts(); + + if (accountsCall != null) { + try { + Response> directoryResponse = accountsCall.execute(); + if (directoryResponse.isSuccessful()) { + accounts.pagination = MastodonHelper.getOffSetPagination(directoryResponse.headers()); + accounts.accounts = directoryResponse.body(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> accountsMutableLiveData.setValue(accounts); + mainHandler.post(myRunnable); + }).start(); + return accountsMutableLiveData; + } + /** * Remove an account from follow suggestions. * diff --git a/app/src/main/res/drawable/ic_baseline_perm_contact_calendar_24.xml b/app/src/main/res/drawable/ic_baseline_perm_contact_calendar_24.xml new file mode 100644 index 00000000..ea5ff25a --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_perm_contact_calendar_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_directory.xml b/app/src/main/res/layout/activity_directory.xml new file mode 100644 index 00000000..c5653185 --- /dev/null +++ b/app/src/main/res/layout/activity_directory.xml @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml index 63e6efef..d415eb68 100644 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -63,6 +63,11 @@ android:icon="@drawable/ic_baseline_account_circle_24" android:title="@string/Suggestions" android:visible="true" /> + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52f4e228..3567f944 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -486,6 +486,7 @@ Unresolved Remote Active + New Pending Disabled Suspended @@ -2206,4 +2207,5 @@ Compact action buttons Buttons at the bottom of messages will not take the whole width Followed by: + Directory \ No newline at end of file diff --git a/src/fdroid/fastlane/metadata/android/en/changelogs/464.txt b/src/fdroid/fastlane/metadata/android/en/changelogs/464.txt index 4ced9f60..b3e900aa 100644 --- a/src/fdroid/fastlane/metadata/android/en/changelogs/464.txt +++ b/src/fdroid/fastlane/metadata/android/en/changelogs/464.txt @@ -1,5 +1,6 @@ Added: - Display familiar followers on profiles +- Display and filter Instance directory Changed: