diff options
author | Thomas <tschneider.ac@gmail.com> | 2023-01-12 14:35:44 +0100 |
---|---|---|
committer | Thomas <tschneider.ac@gmail.com> | 2023-01-12 14:35:44 +0100 |
commit | d5a5f0872798fcd7e58e57c10b21549736e9b86d (patch) | |
tree | 3ceb84a599f09fc4722fdb9f87d52750dda3c414 | |
parent | e03c02cc359f70277a2d5624cb9ff0a37e5b3476 (diff) |
Instance directory
14 files changed, 230 insertions, 2 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6543017c5..61a0d0a4a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -250,6 +250,11 @@ android:label="@string/Suggestions" android:theme="@style/AppThemeBar" /> <activity + android:name=".activities.DirectoryActivity" + android:configChanges="keyboardHidden|orientation|screenSize" + android:label="@string/Directory" + android:theme="@style/AppThemeBar" /> + <activity android:name=".activities.PartnerShipActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/action_about" diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java index ff7cffd95..693e72e43 100644 --- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java @@ -109,6 +109,7 @@ import app.fedilab.android.activities.BaseActivity; import app.fedilab.android.activities.CacheActivity; import app.fedilab.android.activities.ComposeActivity; import app.fedilab.android.activities.ContextActivity; +import app.fedilab.android.activities.DirectoryActivity; import app.fedilab.android.activities.DraftActivity; import app.fedilab.android.activities.FilterActivity; import app.fedilab.android.activities.FollowRequestActivity; @@ -409,6 +410,9 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } else if (id == R.id.nav_suggestions) { Intent intent = new Intent(this, SuggestionActivity.class); startActivity(intent); + } else if (id == R.id.nav_directory) { + Intent intent = new Intent(this, DirectoryActivity.class); + startActivity(intent); } else if (id == R.id.nav_cache) { Intent intent = new Intent(BaseMainActivity.this, CacheActivity.class); startActivity(intent); diff --git a/app/src/main/java/app/fedilab/android/activities/DirectoryActivity.java b/app/src/main/java/app/fedilab/android/activities/DirectoryActivity.java new file mode 100644 index 000000000..73c14fb0e --- /dev/null +++ b/app/src/main/java/app/fedilab/android/activities/DirectoryActivity.java @@ -0,0 +1,83 @@ +package app.fedilab.android.activities; +/* 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 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 28b10231d..b7cba8995 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<List<Account>> 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 e3c5fa665..c4196055c 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 2d31e6059..23fd97a3a 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 b71ef24c5..e8270311d 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 <http://www.gnu.org/licenses>. */ +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 e9f23ec1a..1567a5024 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<Suggestions> getSuggestions(@NonNull String instance, String token, String limit) { suggestionsMutableLiveData = new MutableLiveData<>(); @@ -1622,6 +1622,37 @@ public class AccountsVM extends AndroidViewModel { } /** + * 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<Accounts> getDirectory(@NonNull String instance, String token, Integer offset, Integer limit, String order, Boolean local) { + accountsMutableLiveData = new MutableLiveData<>(); + MastodonAccountsService mastodonAccountsService = init(instance); + new Thread(() -> { + Call<List<Account>> accountsCall = mastodonAccountsService.getDirectory(token, offset, limit, order, local); + Accounts accounts = new Accounts(); + + if (accountsCall != null) { + try { + Response<List<Account>> 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. * * @param accountId id of the account in the database to be removed from 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 000000000..ea5ff25ad --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_perm_contact_calendar_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="#FFFFFF" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M19,3h-1L18,1h-2v2L8,3L8,1L6,1v2L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,6c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM18,18L6,18v-1c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1v1z" /> +</vector> 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 000000000..c56531852 --- /dev/null +++ b/app/src/main/res/layout/activity_directory.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + 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>. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/drawer_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <androidx.fragment.app.FragmentContainerView + android:id="@+id/nav_host_fragment_directory" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:defaultNavHost="true" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> +</LinearLayout>
\ 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 63e6efefa..d415eb68c 100644 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -64,6 +64,11 @@ android:title="@string/Suggestions" android:visible="true" /> <item + android:id="@+id/nav_directory" + android:icon="@drawable/ic_baseline_perm_contact_calendar_24" + android:title="@string/Directory" + android:visible="true" /> + <item android:id="@+id/nav_about_instance" android:icon="@drawable/ic_info_outline_white_24dp" android:title="@string/action_about_instance" diff --git a/app/src/main/res/menu/menu_directory.xml b/app/src/main/res/menu/menu_directory.xml new file mode 100644 index 000000000..00a9bf19f --- /dev/null +++ b/app/src/main/res/menu/menu_directory.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <group + android:id="@+id/order" + android:checkableBehavior="single"> + <item + android:id="@+id/order_active" + android:checked="true" + android:title="@string/active" + app:showAsAction="never" /> + <item + android:id="@+id/order_new" + android:title="@string/_new" + app:showAsAction="never" /> + </group> + <item + android:id="@+id/action_local" + android:checkable="true" + android:title="@string/local" + app:actionViewClass="android.widget.CheckBox" + app:showAsAction="never" /> +</menu> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52f4e2280..3567f9442 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -486,6 +486,7 @@ <string name="unresolved">Unresolved</string> <string name="remote">Remote</string> <string name="active">Active</string> + <string name="_new">New</string> <string name="pending">Pending</string> <string name="disabled">Disabled</string> <string name="suspended">Suspended</string> @@ -2206,4 +2207,5 @@ <string name="set_display_compact_buttons">Compact action buttons</string> <string name="set_display_compact_buttons_description">Buttons at the bottom of messages will not take the whole width</string> <string name="also_followed_by">Followed by:</string> + <string name="Directory">Directory</string> </resources>
\ 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 4ced9f605..b3e900aa2 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: |