From a57659bd69e61efe186f1f1f268e747c5a58aeca Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 19 Nov 2022 16:44:23 +0100 Subject: [PATCH] Comment #477 - Add logic for visiting remote profiles --- .../android/activities/ProfileActivity.java | 5 +- .../android/helper/CrossActionHelper.java | 36 ++++++++++ .../timeline/FragmentMastodonTimeline.java | 65 +++++++++++++++++-- .../timeline/FragmentProfileTimeline.java | 5 +- .../FedilabProfilePageAdapter.java | 7 +- .../FedilabProfileTLPageAdapter.java | 6 +- 6 files changed, 113 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java index 22285dd9d..9f0b497e3 100644 --- a/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ProfileActivity.java @@ -142,13 +142,14 @@ public class ProfileActivity extends BaseActivity { ActionBar actionBar = getSupportActionBar(); Bundle b = getIntent().getExtras(); binding.accountFollow.setEnabled(false); - checkRemotely = false; + checkRemotely = true; if (b != null) { account = (Account) b.getSerializable(Helper.ARG_ACCOUNT); account_id = b.getString(Helper.ARG_USER_ID, null); mention_str = b.getString(Helper.ARG_MENTION, null); checkRemotely = b.getBoolean(Helper.ARG_CHECK_REMOTELY, false); } + checkRemotely = true; postponeEnterTransition(); //Remove title @@ -242,7 +243,7 @@ public class ProfileActivity extends BaseActivity { binding.accountTabLayout.clearOnTabSelectedListeners(); binding.accountTabLayout.removeAllTabs(); //Tablayout for timelines/following/followers - FedilabProfileTLPageAdapter fedilabProfileTLPageAdapter = new FedilabProfileTLPageAdapter(getSupportFragmentManager(), account); + FedilabProfileTLPageAdapter fedilabProfileTLPageAdapter = new FedilabProfileTLPageAdapter(getSupportFragmentManager(), account, checkRemotely); binding.accountTabLayout.addTab(binding.accountTabLayout.newTab().setText(getString(R.string.status_cnt, Helper.withSuffix(account.statuses_count)))); binding.accountTabLayout.addTab(binding.accountTabLayout.newTab().setText(getString(R.string.following_cnt, Helper.withSuffix(account.following_count)))); binding.accountTabLayout.addTab(binding.accountTabLayout.newTab().setText(getString(R.string.followers_cnt, Helper.withSuffix(account.followers_count)))); diff --git a/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java b/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java index 5e2790507..40e621179 100644 --- a/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java @@ -439,6 +439,42 @@ public class CrossActionHelper { } + /** + * Fetch and federate the remote status + */ + public static void fetchAccountInRemoteInstance(@NonNull Context context, String acct, String instance, Callback callback) { + + MastodonSearchService mastodonSearchService = init(context, instance); + new Thread(() -> { + Call resultsCall = mastodonSearchService.search(null, acct, null, "accounts", null, null, null, null, null, null, 1); + Results results = null; + if (resultsCall != null) { + try { + Response resultsResponse = resultsCall.execute(); + if (resultsResponse.isSuccessful()) { + results = resultsResponse.body(); + if (results != null) { + if (results.accounts == null) { + results.accounts = new ArrayList<>(); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Results finalResults = results; + Runnable myRunnable = () -> { + if (finalResults != null && finalResults.accounts != null && finalResults.accounts.size() > 0) { + callback.federatedAccount(finalResults.accounts.get(0)); + } + }; + mainHandler.post(myRunnable); + + }).start(); + } + public enum TypeOfCrossAction { FOLLOW_ACTION, UNFOLLOW_ACTION, diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java index 8d3eebcb3..c3487f4be 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java @@ -45,6 +45,7 @@ import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; +import app.fedilab.android.activities.MainActivity; import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.Pagination; @@ -57,6 +58,7 @@ import app.fedilab.android.client.entities.app.TagTimeline; import app.fedilab.android.client.entities.app.Timeline; import app.fedilab.android.databinding.FragmentPaginationBinding; import app.fedilab.android.exception.DBException; +import app.fedilab.android.helper.CrossActionHelper; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.ThemeHelper; @@ -81,6 +83,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. private StatusAdapter statusAdapter; private Timeline.TimeLineEnum timelineType; private List timelineStatuses; + private boolean checkRemotely; + private String accountIDInRemoteInstance; + //Handle actions that can be done in other fragments private final BroadcastReceiver receive_action = new BroadcastReceiver() { @Override @@ -307,6 +312,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. tagTimeline = (TagTimeline) getArguments().getSerializable(Helper.ARG_TAG_TIMELINE); accountTimeline = (Account) getArguments().getSerializable(Helper.ARG_ACCOUNT); exclude_replies = !getArguments().getBoolean(Helper.ARG_SHOW_REPLIES, true); + checkRemotely = getArguments().getBoolean(Helper.ARG_CHECK_REMOTELY, false); show_pinned = getArguments().getBoolean(Helper.ARG_SHOW_PINNED, false); exclude_reblogs = !getArguments().getBoolean(Helper.ARG_SHOW_REBLOGS, true); media_only = getArguments().getBoolean(Helper.ARG_SHOW_MEDIA_ONY, false); @@ -314,6 +320,13 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. minified = getArguments().getBoolean(Helper.ARG_MINIFIED, false); statusReport = (Status) getArguments().getSerializable(Helper.ARG_STATUS_REPORT); } + //When visiting a profile without being authenticated + if (checkRemotely) { + String[] acctArray = accountTimeline.acct.split("@"); + if (acctArray.length > 1) { + remoteInstance = acctArray[1]; + } + } if (tagTimeline != null) { ident = "@T@" + tagTimeline.name; if (tagTimeline.isART) { @@ -321,7 +334,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. } } else if (list_id != null) { ident = "@l@" + list_id; - } else if (remoteInstance != null) { + } else if (remoteInstance != null && !checkRemotely) { if (pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.NITTER) { ident = "@R@" + pinnedTimeline.remoteInstance.host; } else { @@ -915,10 +928,52 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. } else if (timelineType == Timeline.TimeLineEnum.TAG || timelineType == Timeline.TimeLineEnum.ART) { //TAG TIMELINE routeCommon(direction, fetchingMissing, statusToUpdate); } else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_TIMELINE) { //PROFILE TIMELINES - if (direction == null) { + String tempToken; + String tempInstance; + String accountId = null; + if (checkRemotely) { + tempToken = null; + tempInstance = remoteInstance; + accountId = accountIDInRemoteInstance; + if (accountIDInRemoteInstance == null) { + CrossActionHelper.fetchAccountInRemoteInstance(requireActivity(), accountTimeline.acct, tempInstance, new CrossActionHelper.Callback() { + @Override + public void federatedStatus(Status status) { + } + + @Override + public void federatedAccount(Account account) { + if (account != null) { + accountIDInRemoteInstance = account.id; + accountsVM.getAccountStatuses(tempInstance, null, accountIDInRemoteInstance, null, null, null, null, null, false, true, MastodonHelper.statusesPerCall(requireActivity())) + .observe(getViewLifecycleOwner(), pinnedStatuses -> accountsVM.getAccountStatuses(tempInstance, null, accountIDInRemoteInstance, null, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) + .observe(getViewLifecycleOwner(), otherStatuses -> { + if (otherStatuses != null && otherStatuses.statuses != null && pinnedStatuses != null && pinnedStatuses.statuses != null) { + for (Status status : pinnedStatuses.statuses) { + status.pinned = true; + } + otherStatuses.statuses.addAll(0, pinnedStatuses.statuses); + initializeStatusesCommonView(otherStatuses); + } + })); + } + } + }); + } else { + accountId = accountIDInRemoteInstance; + } + } else { + tempToken = MainActivity.currentToken; + tempInstance = currentInstance; + accountId = accountTimeline.id; + } + if (accountId == null) { + accountId = accountTimeline.id; + } + if (direction == null && !checkRemotely) { if (show_pinned) { //Fetch pinned statuses to display them at the top - accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, null, null, null, null, null, false, true, MastodonHelper.statusesPerCall(requireActivity())) + accountsVM.getAccountStatuses(currentInstance, MainActivity.currentToken, accountId, null, null, null, null, null, false, true, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), pinnedStatuses -> accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, null, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), otherStatuses -> { if (otherStatuses != null && otherStatuses.statuses != null && pinnedStatuses != null && pinnedStatuses.statuses != null) { @@ -930,11 +985,11 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. } })); } else { - accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, null, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) + accountsVM.getAccountStatuses(tempInstance, tempToken, accountId, null, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView); } } else if (direction == DIRECTION.BOTTOM) { - accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, max_id, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) + accountsVM.getAccountStatuses(tempInstance, tempToken, accountId, max_id, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false)); } else { flagLoading = false; diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentProfileTimeline.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentProfileTimeline.java index 3ab5978a4..03c76339f 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentProfileTimeline.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentProfileTimeline.java @@ -37,12 +37,13 @@ public class FragmentProfileTimeline extends Fragment { private Account account; private FragmentProfileTimelinesBinding binding; - + private boolean checkRemotely; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (getArguments() != null) { account = (Account) getArguments().getSerializable(Helper.ARG_ACCOUNT); + checkRemotely = getArguments().getBoolean(Helper.ARG_CHECK_REMOTELY, false); } binding = FragmentProfileTimelinesBinding.inflate(inflater, container, false); return binding.getRoot(); @@ -57,7 +58,7 @@ public class FragmentProfileTimeline extends Fragment { binding.tabLayout.addTab(binding.tabLayout.newTab().setText(getString(R.string.media))); binding.tabLayout.setTabTextColors(ThemeHelper.getAttColor(requireActivity(), R.attr.mTextColor), ContextCompat.getColor(requireActivity(), R.color.cyanea_accent_dark_reference)); binding.tabLayout.setTabIconTint(ThemeHelper.getColorStateList(requireActivity())); - binding.viewpager.setAdapter(new FedilabProfilePageAdapter(getChildFragmentManager(), account)); + binding.viewpager.setAdapter(new FedilabProfilePageAdapter(getChildFragmentManager(), account, checkRemotely)); binding.viewpager.setOffscreenPageLimit(3); binding.viewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(binding.tabLayout)); binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { diff --git a/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfilePageAdapter.java b/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfilePageAdapter.java index 39369fb23..372f7659c 100644 --- a/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfilePageAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfilePageAdapter.java @@ -31,10 +31,12 @@ import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline; public class FedilabProfilePageAdapter extends FragmentStatePagerAdapter { private final Account account; private Fragment mCurrentFragment; + private final boolean checkRemotely; - public FedilabProfilePageAdapter(FragmentManager fm, Account account) { + public FedilabProfilePageAdapter(FragmentManager fm, Account account, boolean remotely) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); this.account = account; + this.checkRemotely = remotely; } public Fragment getCurrentFragment() { @@ -62,6 +64,7 @@ public class FedilabProfilePageAdapter extends FragmentStatePagerAdapter { bundle.putBoolean(Helper.ARG_SHOW_PINNED, true); bundle.putBoolean(Helper.ARG_SHOW_REPLIES, false); bundle.putBoolean(Helper.ARG_SHOW_REBLOGS, true); + bundle.putBoolean(Helper.ARG_CHECK_REMOTELY, checkRemotely); fragmentProfileTimeline.setArguments(bundle); return fragmentProfileTimeline; case 1: @@ -71,11 +74,13 @@ public class FedilabProfilePageAdapter extends FragmentStatePagerAdapter { bundle.putBoolean(Helper.ARG_SHOW_PINNED, false); bundle.putBoolean(Helper.ARG_SHOW_REPLIES, true); bundle.putBoolean(Helper.ARG_SHOW_REBLOGS, false); + bundle.putBoolean(Helper.ARG_CHECK_REMOTELY, checkRemotely); fragmentProfileTimeline.setArguments(bundle); return fragmentProfileTimeline; case 2: FragmentMediaProfile fragmentMediaProfile = new FragmentMediaProfile(); bundle.putSerializable(Helper.ARG_ACCOUNT, account); + bundle.putBoolean(Helper.ARG_CHECK_REMOTELY, checkRemotely); fragmentMediaProfile.setArguments(bundle); return fragmentMediaProfile; default: diff --git a/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfileTLPageAdapter.java b/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfileTLPageAdapter.java index 585a6b487..ca2ebb26a 100644 --- a/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfileTLPageAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/pageadapter/FedilabProfileTLPageAdapter.java @@ -31,10 +31,12 @@ import app.fedilab.android.ui.fragment.timeline.FragmentProfileTimeline; public class FedilabProfileTLPageAdapter extends FragmentStatePagerAdapter { private final Account account; private Fragment mCurrentFragment; + private final boolean checkRemotely; - public FedilabProfileTLPageAdapter(FragmentManager fm, Account account) { + public FedilabProfileTLPageAdapter(FragmentManager fm, Account account, boolean remotely) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); this.account = account; + this.checkRemotely = remotely; } public Fragment getCurrentFragment() { @@ -57,6 +59,7 @@ public class FedilabProfileTLPageAdapter extends FragmentStatePagerAdapter { FragmentProfileTimeline fragmentProfileTimeline = new FragmentProfileTimeline(); Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_ACCOUNT, account); + bundle.putSerializable(Helper.ARG_CHECK_REMOTELY, checkRemotely); fragmentProfileTimeline.setArguments(bundle); return fragmentProfileTimeline; case 1: @@ -64,6 +67,7 @@ public class FedilabProfileTLPageAdapter extends FragmentStatePagerAdapter { FragmentMastodonAccount fragmentMastodonAccount = new FragmentMastodonAccount(); bundle = new Bundle(); bundle.putSerializable(Helper.ARG_ACCOUNT, account); + bundle.putSerializable(Helper.ARG_CHECK_REMOTELY, checkRemotely); bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + position); bundle.putSerializable(Helper.ARG_FOLLOW_TYPE, position == 1 ? follow_type.FOLLOWING : follow_type.FOLLOWERS); fragmentMastodonAccount.setArguments(bundle);