|
|
@ -24,16 +24,17 @@ import android.widget.TextView; |
|
|
|
import android.widget.Toast; |
|
|
|
|
|
|
|
import androidx.activity.OnBackPressedCallback; |
|
|
|
import androidx.activity.OnBackPressedDispatcher; |
|
|
|
import androidx.annotation.NonNull; |
|
|
|
import androidx.annotation.Nullable; |
|
|
|
import androidx.appcompat.app.ActionBar; |
|
|
|
import androidx.appcompat.app.AlertDialog; |
|
|
|
import androidx.coordinatorlayout.widget.CoordinatorLayout; |
|
|
|
import androidx.core.content.PermissionChecker; |
|
|
|
import androidx.fragment.app.Fragment; |
|
|
|
import androidx.fragment.app.FragmentManager; |
|
|
|
import androidx.fragment.app.FragmentTransaction; |
|
|
|
import androidx.lifecycle.ViewModelProvider; |
|
|
|
import androidx.navigation.NavController; |
|
|
|
import androidx.navigation.NavDirections; |
|
|
|
import androidx.navigation.fragment.NavHostFragment; |
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager; |
|
|
@ -46,7 +47,6 @@ import com.facebook.imagepipeline.image.ImageInfo; |
|
|
|
import com.google.android.material.snackbar.BaseTransientBottomBar; |
|
|
|
import com.google.android.material.snackbar.Snackbar; |
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Date; |
|
|
|
import java.util.List; |
|
|
@ -54,24 +54,25 @@ import java.util.List; |
|
|
|
import awais.instagrabber.ProfileNavGraphDirections; |
|
|
|
import awais.instagrabber.R; |
|
|
|
import awais.instagrabber.activities.MainActivity; |
|
|
|
import awais.instagrabber.adapters.FeedAdapterV2; |
|
|
|
import awais.instagrabber.adapters.HighlightsAdapter; |
|
|
|
import awais.instagrabber.adapters.PostsAdapter; |
|
|
|
import awais.instagrabber.asyncs.HighlightsFetcher; |
|
|
|
import awais.instagrabber.asyncs.PostsFetcher; |
|
|
|
import awais.instagrabber.asyncs.ProfileFetcher; |
|
|
|
import awais.instagrabber.asyncs.ProfilePostFetchService; |
|
|
|
import awais.instagrabber.asyncs.UsernameFetcher; |
|
|
|
import awais.instagrabber.asyncs.direct_messages.CreateThreadAction; |
|
|
|
import awais.instagrabber.customviews.PrimaryActionModeCallback; |
|
|
|
import awais.instagrabber.customviews.PrimaryActionModeCallback.CallbacksHelper; |
|
|
|
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager; |
|
|
|
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration; |
|
|
|
import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; |
|
|
|
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; |
|
|
|
import awais.instagrabber.databinding.FragmentProfileBinding; |
|
|
|
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; |
|
|
|
import awais.instagrabber.dialogs.ProfilePicDialogFragment; |
|
|
|
import awais.instagrabber.fragments.PostViewV2Fragment; |
|
|
|
import awais.instagrabber.interfaces.FetchListener; |
|
|
|
import awais.instagrabber.interfaces.MentionClickListener; |
|
|
|
import awais.instagrabber.models.PostModel; |
|
|
|
import awais.instagrabber.models.FeedModel; |
|
|
|
import awais.instagrabber.models.PostsLayoutPreferences; |
|
|
|
import awais.instagrabber.models.ProfileModel; |
|
|
|
import awais.instagrabber.models.StoryModel; |
|
|
|
import awais.instagrabber.models.enums.DownloadMethod; |
|
|
@ -86,17 +87,17 @@ import awais.instagrabber.utils.DownloadUtils; |
|
|
|
import awais.instagrabber.utils.TextUtils; |
|
|
|
import awais.instagrabber.utils.Utils; |
|
|
|
import awais.instagrabber.viewmodels.HighlightsViewModel; |
|
|
|
import awais.instagrabber.viewmodels.PostsViewModel; |
|
|
|
import awais.instagrabber.webservices.FriendshipService; |
|
|
|
import awais.instagrabber.webservices.ServiceCallback; |
|
|
|
import awais.instagrabber.webservices.StoriesService; |
|
|
|
import awaisomereport.LogCollector; |
|
|
|
|
|
|
|
import static awais.instagrabber.utils.Utils.logCollector; |
|
|
|
import static androidx.core.content.PermissionChecker.checkSelfPermission; |
|
|
|
import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; |
|
|
|
import static awais.instagrabber.utils.Utils.settingsHelper; |
|
|
|
|
|
|
|
public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { |
|
|
|
private static final String TAG = "ProfileFragment"; |
|
|
|
private static final int STORAGE_PERM_REQUEST_CODE = 8020; |
|
|
|
|
|
|
|
private MainActivity fragmentActivity; |
|
|
|
private CoordinatorLayout root; |
|
|
@ -105,21 +106,18 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
private String cookie; |
|
|
|
private String username; |
|
|
|
private ProfileModel profileModel; |
|
|
|
private PostsViewModel postsViewModel; |
|
|
|
private PostsAdapter postsAdapter; |
|
|
|
private ActionMode actionMode; |
|
|
|
private Handler usernameSettingHandler; |
|
|
|
private FriendshipService friendshipService; |
|
|
|
private StoriesService storiesService; |
|
|
|
private boolean shouldRefresh = true, hasStories = false; |
|
|
|
private boolean hasNextPage; |
|
|
|
private String endCursor; |
|
|
|
private AsyncTask<Void, Void, List<PostModel>> currentlyExecuting; |
|
|
|
private boolean isPullToRefresh; |
|
|
|
private boolean shouldRefresh = true; |
|
|
|
private boolean hasStories = false; |
|
|
|
private HighlightsAdapter highlightsAdapter; |
|
|
|
private HighlightsViewModel highlightsViewModel; |
|
|
|
private MenuItem blockMenuItem; |
|
|
|
private MenuItem restrictMenuItem; |
|
|
|
private boolean highlightsFetching; |
|
|
|
|
|
|
|
private final Runnable usernameSettingRunnable = () -> { |
|
|
|
final ActionBar actionBar = fragmentActivity.getSupportActionBar(); |
|
|
@ -165,36 +163,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
return false; |
|
|
|
} |
|
|
|
}); |
|
|
|
private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() { |
|
|
|
@Override |
|
|
|
public void onResult(final List<PostModel> result) { |
|
|
|
binding.swipeRefreshLayout.setRefreshing(false); |
|
|
|
if (result == null || result.isEmpty()) { |
|
|
|
binding.privatePage1.setImageResource(R.drawable.ic_cancel); |
|
|
|
binding.privatePage2.setText(R.string.empty_acc); |
|
|
|
binding.privatePage.setVisibility(View.VISIBLE); |
|
|
|
return; |
|
|
|
} else { |
|
|
|
binding.privatePage.setVisibility(View.GONE); |
|
|
|
} |
|
|
|
binding.mainPosts.post(() -> binding.mainPosts.setVisibility(View.VISIBLE)); |
|
|
|
final List<PostModel> postModels = postsViewModel.getList().getValue(); |
|
|
|
List<PostModel> finalList = postModels == null || postModels.isEmpty() ? new ArrayList<>() |
|
|
|
: new ArrayList<>(postModels); |
|
|
|
if (isPullToRefresh) { |
|
|
|
finalList = result; |
|
|
|
isPullToRefresh = false; |
|
|
|
} else { |
|
|
|
finalList.addAll(result); |
|
|
|
} |
|
|
|
postsViewModel.getList().postValue(finalList); |
|
|
|
final PostModel lastPostModel = result.get(result.size() - 1); |
|
|
|
if (lastPostModel == null) return; |
|
|
|
endCursor = lastPostModel.getEndCursor(); |
|
|
|
hasNextPage = lastPostModel.hasNextPage(); |
|
|
|
lastPostModel.setPageCursor(false, null); |
|
|
|
} |
|
|
|
}; |
|
|
|
private final MentionClickListener mentionClickListener = (view, text, isHashtag, isLocation) -> { |
|
|
|
Log.d(TAG, "action..."); |
|
|
|
if (isHashtag) { |
|
|
@ -213,6 +181,92 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
action.setUsername("@" + text); |
|
|
|
NavHostFragment.findNavController(this).navigate(action); |
|
|
|
}; |
|
|
|
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() { |
|
|
|
@Override |
|
|
|
public void onPostClick(final FeedModel feedModel, final View profilePicView, final View mainPostImage) { |
|
|
|
openPostDialog(feedModel, profilePicView, mainPostImage, -1); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onSliderClick(final FeedModel feedModel, final int position) { |
|
|
|
openPostDialog(feedModel, null, null, position); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onCommentsClick(final FeedModel feedModel) { |
|
|
|
final NavDirections commentsAction = FeedFragmentDirections.actionGlobalCommentsViewerFragment( |
|
|
|
feedModel.getShortCode(), |
|
|
|
feedModel.getPostId(), |
|
|
|
feedModel.getProfileModel().getId() |
|
|
|
); |
|
|
|
NavHostFragment.findNavController(ProfileFragment.this).navigate(commentsAction); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onDownloadClick(final FeedModel feedModel) { |
|
|
|
final Context context = getContext(); |
|
|
|
if (context == null) return; |
|
|
|
if (checkSelfPermission(context, WRITE_PERMISSION) == PermissionChecker.PERMISSION_GRANTED) { |
|
|
|
showDownloadDialog(feedModel); |
|
|
|
return; |
|
|
|
} |
|
|
|
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onHashtagClick(final String hashtag) { |
|
|
|
final NavDirections action = FeedFragmentDirections.actionGlobalHashTagFragment(hashtag); |
|
|
|
NavHostFragment.findNavController(ProfileFragment.this).navigate(action); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onLocationClick(final FeedModel feedModel) { |
|
|
|
final NavDirections action = FeedFragmentDirections.actionGlobalLocationFragment(feedModel.getLocationId()); |
|
|
|
NavHostFragment.findNavController(ProfileFragment.this).navigate(action); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onMentionClick(final String mention) { |
|
|
|
navigateToProfile(mention.trim()); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onNameClick(final FeedModel feedModel, final View profilePicView) { |
|
|
|
navigateToProfile("@" + feedModel.getProfileModel().getUsername()); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onProfilePicClick(final FeedModel feedModel, final View profilePicView) { |
|
|
|
navigateToProfile("@" + feedModel.getProfileModel().getUsername()); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onURLClick(final String url) { |
|
|
|
Utils.openURL(getContext(), url); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onEmailClick(final String emailId) { |
|
|
|
Utils.openEmailAddress(getContext(), emailId); |
|
|
|
} |
|
|
|
|
|
|
|
private void openPostDialog(final FeedModel feedModel, |
|
|
|
final View profilePicView, |
|
|
|
final View mainPostImage, |
|
|
|
final int position) { |
|
|
|
final PostViewV2Fragment.Builder builder = PostViewV2Fragment |
|
|
|
.builder(feedModel); |
|
|
|
if (position >= 0) { |
|
|
|
builder.setPosition(position); |
|
|
|
} |
|
|
|
final PostViewV2Fragment fragment = builder |
|
|
|
.setSharedProfilePicElement(profilePicView) |
|
|
|
.setSharedMainPostElement(mainPostImage) |
|
|
|
.build(); |
|
|
|
fragment.show(getChildFragmentManager(), "post_view"); |
|
|
|
} |
|
|
|
}; |
|
|
|
private boolean postsSetupDone = false; |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onCreate(@Nullable final Bundle savedInstanceState) { |
|
|
@ -267,7 +321,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
@Override |
|
|
|
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) { |
|
|
|
inflater.inflate(R.menu.profile_menu, menu); |
|
|
|
// favMenuItem = menu.findItem(R.id.favourites); |
|
|
|
blockMenuItem = menu.findItem(R.id.block); |
|
|
|
if (blockMenuItem != null) { |
|
|
|
blockMenuItem.setVisible(false); |
|
|
@ -280,6 +333,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean onOptionsItemSelected(@NonNull final MenuItem item) { |
|
|
|
if (item.getItemId() == R.id.layout) { |
|
|
|
showPostsLayoutPreferences(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
if (item.getItemId() == R.id.restrict) { |
|
|
|
if (!isLoggedIn) return false; |
|
|
|
final String action = profileModel.getRestricted() ? "Unrestrict" : "Restrict"; |
|
|
@ -346,10 +403,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onRefresh() { |
|
|
|
isPullToRefresh = true; |
|
|
|
endCursor = null; |
|
|
|
fetchProfileDetails(); |
|
|
|
fetchPosts(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@ -359,9 +413,9 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
if (usernameSettingHandler != null) { |
|
|
|
usernameSettingHandler.removeCallbacks(usernameSettingRunnable); |
|
|
|
} |
|
|
|
if (postsViewModel != null) { |
|
|
|
postsViewModel.getList().postValue(Collections.emptyList()); |
|
|
|
} |
|
|
|
// if (postsViewModel != null) { |
|
|
|
// postsViewModel.getList().postValue(Collections.emptyList()); |
|
|
|
// } |
|
|
|
if (highlightsViewModel != null) { |
|
|
|
highlightsViewModel.getList().postValue(Collections.emptyList()); |
|
|
|
} |
|
|
@ -385,7 +439,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
return; |
|
|
|
} |
|
|
|
binding.swipeRefreshLayout.setEnabled(true); |
|
|
|
setupPosts(); |
|
|
|
setupHighlights(); |
|
|
|
setupCommonListeners(); |
|
|
|
fetchUsername(); |
|
|
@ -444,87 +497,18 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
Toast.makeText(context, R.string.error_loading_profile, Toast.LENGTH_SHORT).show(); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (!postsSetupDone) { |
|
|
|
setupPosts(); |
|
|
|
} else { |
|
|
|
binding.postsRecyclerView.refresh(); |
|
|
|
} |
|
|
|
binding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE); |
|
|
|
final String profileId = profileModel.getId(); |
|
|
|
|
|
|
|
final String myId = CookieUtils.getUserIdFromCookie(cookie); |
|
|
|
if (isLoggedIn) { |
|
|
|
storiesService.getUserStory(profileId, |
|
|
|
profileModel.getUsername(), |
|
|
|
false, |
|
|
|
false, |
|
|
|
false, |
|
|
|
new ServiceCallback<List<StoryModel>>() { |
|
|
|
@Override |
|
|
|
public void onSuccess(final List<StoryModel> storyModels) { |
|
|
|
if (storyModels != null && !storyModels.isEmpty()) { |
|
|
|
binding.mainProfileImage.setStoriesBorder(); |
|
|
|
hasStories = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onFailure(final Throwable t) { |
|
|
|
Log.e(TAG, "Error", t); |
|
|
|
} |
|
|
|
}); |
|
|
|
new HighlightsFetcher(profileId, |
|
|
|
result -> { |
|
|
|
if (result != null) { |
|
|
|
binding.highlightsList.setVisibility(View.VISIBLE); |
|
|
|
highlightsViewModel.getList().postValue(result); |
|
|
|
} else binding.highlightsList.setVisibility(View.GONE); |
|
|
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
|
|
if (profileId.equals(myId)) { |
|
|
|
binding.btnTagged.setVisibility(View.VISIBLE); |
|
|
|
binding.btnSaved.setVisibility(View.VISIBLE); |
|
|
|
binding.btnLiked.setVisibility(View.VISIBLE); |
|
|
|
binding.btnDM.setVisibility(View.GONE); |
|
|
|
binding.btnSaved.setText(R.string.saved); |
|
|
|
} else { |
|
|
|
binding.btnTagged.setVisibility(View.GONE); |
|
|
|
binding.btnSaved.setVisibility(View.GONE); |
|
|
|
binding.btnLiked.setVisibility(View.GONE); |
|
|
|
binding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism? |
|
|
|
binding.btnFollow.setVisibility(View.VISIBLE); |
|
|
|
if (profileModel.getFollowing()) { |
|
|
|
binding.btnFollow.setText(R.string.unfollow); |
|
|
|
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); |
|
|
|
} else if (profileModel.getRequested()) { |
|
|
|
binding.btnFollow.setText(R.string.cancel); |
|
|
|
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); |
|
|
|
} else { |
|
|
|
binding.btnFollow.setText(R.string.follow); |
|
|
|
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_24); |
|
|
|
} |
|
|
|
if (restrictMenuItem != null) { |
|
|
|
restrictMenuItem.setVisible(true); |
|
|
|
if (profileModel.getRestricted()) { |
|
|
|
restrictMenuItem.setTitle(R.string.unrestrict); |
|
|
|
} else { |
|
|
|
restrictMenuItem.setTitle(R.string.restrict); |
|
|
|
} |
|
|
|
} |
|
|
|
binding.btnTagged.setVisibility(profileModel.isReallyPrivate() ? View.GONE : View.VISIBLE); |
|
|
|
if (blockMenuItem != null) { |
|
|
|
blockMenuItem.setVisible(true); |
|
|
|
if (profileModel.getBlocked()) { |
|
|
|
blockMenuItem.setTitle(R.string.unblock); |
|
|
|
} else { |
|
|
|
blockMenuItem.setTitle(R.string.block); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (!profileModel.isReallyPrivate() && restrictMenuItem != null) { |
|
|
|
restrictMenuItem.setVisible(true); |
|
|
|
if (profileModel.getRestricted()) { |
|
|
|
restrictMenuItem.setTitle(R.string.unrestrict); |
|
|
|
} else { |
|
|
|
restrictMenuItem.setTitle(R.string.restrict); |
|
|
|
} |
|
|
|
} |
|
|
|
fetchStoryAndHighlights(profileId); |
|
|
|
} |
|
|
|
setupButtons(profileId, myId); |
|
|
|
if (!profileId.equals(myId)) { |
|
|
|
binding.favCb.setVisibility(View.VISIBLE); |
|
|
|
final boolean isFav = Utils.dataBox.getFavorite(username.substring(1), FavoriteType.USER) != null; |
|
|
@ -572,8 +556,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
: profileModel.getName()); |
|
|
|
|
|
|
|
CharSequence biography = profileModel.getBiography(); |
|
|
|
// binding.mainBiography.setCaptionIsExpandable(true); |
|
|
|
// binding.mainBiography.setCaptionIsExpanded(true); |
|
|
|
if (TextUtils.hasMentions(biography)) { |
|
|
|
biography = TextUtils.getMentionText(biography); |
|
|
|
binding.mainBiography.setText(biography, TextView.BufferType.SPANNABLE); |
|
|
@ -618,7 +600,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
} |
|
|
|
|
|
|
|
binding.swipeRefreshLayout.setRefreshing(true); |
|
|
|
binding.mainPosts.setVisibility(View.VISIBLE); |
|
|
|
binding.postsRecyclerView.setVisibility(View.VISIBLE); |
|
|
|
fetchPosts(); |
|
|
|
} else { |
|
|
|
binding.mainFollowers.setClickable(false); |
|
|
@ -628,10 +610,94 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
binding.privatePage1.setImageResource(R.drawable.lock); |
|
|
|
binding.privatePage2.setText(R.string.priv_acc); |
|
|
|
binding.privatePage.setVisibility(View.VISIBLE); |
|
|
|
binding.mainPosts.setVisibility(View.GONE); |
|
|
|
binding.postsRecyclerView.setVisibility(View.GONE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void setupButtons(final String profileId, final String myId) { |
|
|
|
if (isLoggedIn) { |
|
|
|
if (profileId.equals(myId)) { |
|
|
|
binding.btnTagged.setVisibility(View.VISIBLE); |
|
|
|
binding.btnSaved.setVisibility(View.VISIBLE); |
|
|
|
binding.btnLiked.setVisibility(View.VISIBLE); |
|
|
|
binding.btnDM.setVisibility(View.GONE); |
|
|
|
binding.btnSaved.setText(R.string.saved); |
|
|
|
return; |
|
|
|
} |
|
|
|
binding.btnTagged.setVisibility(View.GONE); |
|
|
|
binding.btnSaved.setVisibility(View.GONE); |
|
|
|
binding.btnLiked.setVisibility(View.GONE); |
|
|
|
binding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism? |
|
|
|
binding.btnFollow.setVisibility(View.VISIBLE); |
|
|
|
if (profileModel.getFollowing()) { |
|
|
|
binding.btnFollow.setText(R.string.unfollow); |
|
|
|
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); |
|
|
|
} else if (profileModel.getRequested()) { |
|
|
|
binding.btnFollow.setText(R.string.cancel); |
|
|
|
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); |
|
|
|
} else { |
|
|
|
binding.btnFollow.setText(R.string.follow); |
|
|
|
binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_24); |
|
|
|
} |
|
|
|
if (restrictMenuItem != null) { |
|
|
|
restrictMenuItem.setVisible(true); |
|
|
|
if (profileModel.getRestricted()) { |
|
|
|
restrictMenuItem.setTitle(R.string.unrestrict); |
|
|
|
} else { |
|
|
|
restrictMenuItem.setTitle(R.string.restrict); |
|
|
|
} |
|
|
|
} |
|
|
|
binding.btnTagged.setVisibility(profileModel.isReallyPrivate() ? View.GONE : View.VISIBLE); |
|
|
|
if (blockMenuItem != null) { |
|
|
|
blockMenuItem.setVisible(true); |
|
|
|
if (profileModel.getBlocked()) { |
|
|
|
blockMenuItem.setTitle(R.string.unblock); |
|
|
|
} else { |
|
|
|
blockMenuItem.setTitle(R.string.block); |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
if (!profileModel.isReallyPrivate() && restrictMenuItem != null) { |
|
|
|
restrictMenuItem.setVisible(true); |
|
|
|
if (profileModel.getRestricted()) { |
|
|
|
restrictMenuItem.setTitle(R.string.unrestrict); |
|
|
|
} else { |
|
|
|
restrictMenuItem.setTitle(R.string.restrict); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void fetchStoryAndHighlights(final String profileId) { |
|
|
|
storiesService.getUserStory(profileId, |
|
|
|
profileModel.getUsername(), |
|
|
|
false, |
|
|
|
false, |
|
|
|
false, |
|
|
|
new ServiceCallback<List<StoryModel>>() { |
|
|
|
@Override |
|
|
|
public void onSuccess(final List<StoryModel> storyModels) { |
|
|
|
if (storyModels != null && !storyModels.isEmpty()) { |
|
|
|
binding.mainProfileImage.setStoriesBorder(); |
|
|
|
hasStories = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void onFailure(final Throwable t) { |
|
|
|
Log.e(TAG, "Error", t); |
|
|
|
} |
|
|
|
}); |
|
|
|
new HighlightsFetcher(profileId, |
|
|
|
result -> { |
|
|
|
highlightsFetching = false; |
|
|
|
if (result != null) { |
|
|
|
binding.highlightsList.setVisibility(View.VISIBLE); |
|
|
|
highlightsViewModel.getList().postValue(result); |
|
|
|
} else binding.highlightsList.setVisibility(View.GONE); |
|
|
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
|
|
} |
|
|
|
|
|
|
|
private void setupCommonListeners() { |
|
|
|
|
|
|
|
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); |
|
|
@ -781,62 +847,60 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
} |
|
|
|
|
|
|
|
private void setupPosts() { |
|
|
|
postsViewModel = new ViewModelProvider(this).get(PostsViewModel.class); |
|
|
|
final Context context = getContext(); |
|
|
|
if (context == null) return; |
|
|
|
final GridAutofitLayoutManager layoutManager = new GridAutofitLayoutManager(context, Utils.convertDpToPx(110)); |
|
|
|
binding.mainPosts.setLayoutManager(layoutManager); |
|
|
|
binding.mainPosts.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(4))); |
|
|
|
postsAdapter = new PostsAdapter((postModel, position) -> { |
|
|
|
if (postsAdapter.isSelecting()) { |
|
|
|
if (actionMode == null) return; |
|
|
|
final String title = getString(R.string.number_selected, |
|
|
|
postsAdapter.getSelectedModels().size()); |
|
|
|
actionMode.setTitle(title); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (checkAndResetAction()) return; |
|
|
|
final List<PostModel> postModels = postsViewModel.getList().getValue(); |
|
|
|
if (postModels == null || postModels.size() == 0) return; |
|
|
|
if (postModels.get(0) == null) return; |
|
|
|
final String postId = isLoggedIn ? postModels.get(0).getPostId() : postModels.get(0).getShortCode(); |
|
|
|
final boolean isId = isLoggedIn && postId != null; |
|
|
|
final String[] idsOrShortCodes = new String[postModels.size()]; |
|
|
|
for (int i = 0; i < postModels.size(); i++) { |
|
|
|
idsOrShortCodes[i] = isId ? postModels.get(i).getPostId() |
|
|
|
: postModels.get(i).getShortCode(); |
|
|
|
} |
|
|
|
final NavDirections action = ProfileFragmentDirections.actionGlobalPostViewFragment( |
|
|
|
position, |
|
|
|
idsOrShortCodes, |
|
|
|
isId); |
|
|
|
NavHostFragment.findNavController(this).navigate(action); |
|
|
|
binding.postsRecyclerView.setViewModelStoreOwner(this) |
|
|
|
.setLifeCycleOwner(this) |
|
|
|
.setPostFetchService(new ProfilePostFetchService(profileModel)) |
|
|
|
.setLayoutPreferences(PostsLayoutPreferences.fromJson(settingsHelper.getString(Constants.PREF_PROFILE_POSTS_LAYOUT))) |
|
|
|
.addFetchStatusChangeListener(fetching -> updateSwipeRefreshState()) |
|
|
|
.setFeedItemCallback(feedItemCallback) |
|
|
|
.init(); |
|
|
|
binding.swipeRefreshLayout.setRefreshing(true); |
|
|
|
postsSetupDone = true; |
|
|
|
// postsAdapter = new PostsAdapter((postModel, position) -> { |
|
|
|
// if (postsAdapter.isSelecting()) { |
|
|
|
// if (actionMode == null) return; |
|
|
|
// final String title = getString(R.string.number_selected, |
|
|
|
// postsAdapter.getSelectedModels().size()); |
|
|
|
// actionMode.setTitle(title); |
|
|
|
// return; |
|
|
|
// } |
|
|
|
// if (checkAndResetAction()) return; |
|
|
|
// final List<PostModel> postModels = postsViewModel.getList().getValue(); |
|
|
|
// if (postModels == null || postModels.size() == 0) return; |
|
|
|
// if (postModels.get(0) == null) return; |
|
|
|
// final String postId = isLoggedIn ? postModels.get(0).getPostId() : postModels.get(0).getShortCode(); |
|
|
|
// final boolean isId = isLoggedIn && postId != null; |
|
|
|
// final String[] idsOrShortCodes = new String[postModels.size()]; |
|
|
|
// for (int i = 0; i < postModels.size(); i++) { |
|
|
|
// idsOrShortCodes[i] = isId ? postModels.get(i).getPostId() |
|
|
|
// : postModels.get(i).getShortCode(); |
|
|
|
// } |
|
|
|
// final NavDirections action = ProfileFragmentDirections.actionGlobalPostViewFragment( |
|
|
|
// position, |
|
|
|
// idsOrShortCodes, |
|
|
|
// isId); |
|
|
|
// NavHostFragment.findNavController(this).navigate(action); |
|
|
|
// |
|
|
|
// }, (model, position) -> { |
|
|
|
// if (!postsAdapter.isSelecting()) { |
|
|
|
// checkAndResetAction(); |
|
|
|
// return true; |
|
|
|
// } |
|
|
|
// if (onBackPressedCallback.isEnabled()) { |
|
|
|
// return true; |
|
|
|
// } |
|
|
|
// final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher(); |
|
|
|
// onBackPressedCallback.setEnabled(true); |
|
|
|
// actionMode = fragmentActivity.startActionMode(multiSelectAction); |
|
|
|
// final String title = getString(R.string.number_selected, 1); |
|
|
|
// actionMode.setTitle(title); |
|
|
|
// onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback); |
|
|
|
// return true; |
|
|
|
// }); |
|
|
|
} |
|
|
|
|
|
|
|
}, (model, position) -> { |
|
|
|
if (!postsAdapter.isSelecting()) { |
|
|
|
checkAndResetAction(); |
|
|
|
return true; |
|
|
|
} |
|
|
|
if (onBackPressedCallback.isEnabled()) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher(); |
|
|
|
onBackPressedCallback.setEnabled(true); |
|
|
|
actionMode = fragmentActivity.startActionMode(multiSelectAction); |
|
|
|
final String title = getString(R.string.number_selected, 1); |
|
|
|
actionMode.setTitle(title); |
|
|
|
onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback); |
|
|
|
return true; |
|
|
|
}); |
|
|
|
postsViewModel.getList().observe(fragmentActivity, postsAdapter::submitList); |
|
|
|
binding.mainPosts.setAdapter(postsAdapter); |
|
|
|
final RecyclerLazyLoader lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> { |
|
|
|
if (!hasNextPage) return; |
|
|
|
binding.swipeRefreshLayout.setRefreshing(true); |
|
|
|
fetchPosts(); |
|
|
|
endCursor = null; |
|
|
|
}); |
|
|
|
binding.mainPosts.addOnScrollListener(lazyLoader); |
|
|
|
private void updateSwipeRefreshState() { |
|
|
|
binding.swipeRefreshLayout.setRefreshing(binding.postsRecyclerView.isFetching() || highlightsFetching); |
|
|
|
} |
|
|
|
|
|
|
|
private void setupHighlights() { |
|
|
@ -855,22 +919,11 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
} |
|
|
|
|
|
|
|
private void fetchPosts() { |
|
|
|
stopCurrentExecutor(); |
|
|
|
// stopCurrentExecutor(); |
|
|
|
binding.swipeRefreshLayout.setRefreshing(true); |
|
|
|
currentlyExecuting = new PostsFetcher(profileModel.getId(), PostItemType.MAIN, endCursor, postsFetchListener) |
|
|
|
.setUsername(profileModel.getUsername()) |
|
|
|
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
|
|
} |
|
|
|
|
|
|
|
public void stopCurrentExecutor() { |
|
|
|
if (currentlyExecuting != null) { |
|
|
|
try { |
|
|
|
currentlyExecuting.cancel(true); |
|
|
|
} catch (final Exception e) { |
|
|
|
if (logCollector != null) logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor"); |
|
|
|
Log.e(TAG, "", e); |
|
|
|
} |
|
|
|
} |
|
|
|
// currentlyExecuting = new PostsFetcher(profileModel.getId(), PostItemType.MAIN, endCursor, postsFetchListener) |
|
|
|
// .setUsername(profileModel.getUsername()) |
|
|
|
// .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
|
|
|
} |
|
|
|
|
|
|
|
private boolean checkAndResetAction() { |
|
|
@ -887,4 +940,60 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
private void navigateToProfile(final String username) { |
|
|
|
final NavController navController = NavHostFragment.findNavController(this); |
|
|
|
final Bundle bundle = new Bundle(); |
|
|
|
bundle.putString("username", username); |
|
|
|
navController.navigate(R.id.action_global_profileFragment, bundle); |
|
|
|
} |
|
|
|
|
|
|
|
private void showDownloadDialog(final FeedModel feedModel) { |
|
|
|
final Context context = getContext(); |
|
|
|
if (context == null) return; |
|
|
|
DownloadUtils.download(context, feedModel); |
|
|
|
// switch (feedModel.getItemType()) { |
|
|
|
// case MEDIA_TYPE_IMAGE: |
|
|
|
// case MEDIA_TYPE_VIDEO: |
|
|
|
// break; |
|
|
|
// case MEDIA_TYPE_SLIDER: |
|
|
|
// break; |
|
|
|
// } |
|
|
|
// final List<ViewerPostModel> postModelsToDownload = new ArrayList<>(); |
|
|
|
// // if (!session) { |
|
|
|
// final DialogInterface.OnClickListener clickListener = (dialog, which) -> { |
|
|
|
// if (which == DialogInterface.BUTTON_NEGATIVE) { |
|
|
|
// postModelsToDownload.addAll(postModels); |
|
|
|
// } else if (which == DialogInterface.BUTTON_POSITIVE) { |
|
|
|
// postModelsToDownload.add(postModels.get(childPosition)); |
|
|
|
// } else { |
|
|
|
// session = true; |
|
|
|
// postModelsToDownload.add(postModels.get(childPosition)); |
|
|
|
// } |
|
|
|
// if (postModelsToDownload.size() > 0) { |
|
|
|
// DownloadUtils.batchDownload(context, |
|
|
|
// username, |
|
|
|
// DownloadMethod.DOWNLOAD_POST_VIEWER, |
|
|
|
// postModelsToDownload); |
|
|
|
// } |
|
|
|
// }; |
|
|
|
// new AlertDialog.Builder(context) |
|
|
|
// .setTitle(R.string.post_viewer_download_dialog_title) |
|
|
|
// .setMessage(R.string.post_viewer_download_message) |
|
|
|
// .setNeutralButton(R.string.post_viewer_download_session, clickListener) |
|
|
|
// .setPositiveButton(R.string.post_viewer_download_current, clickListener) |
|
|
|
// .setNegativeButton(R.string.post_viewer_download_album, clickListener).show(); |
|
|
|
// } else { |
|
|
|
// DownloadUtils.batchDownload(context, |
|
|
|
// username, |
|
|
|
// DownloadMethod.DOWNLOAD_POST_VIEWER, |
|
|
|
// Collections.singletonList(postModels.get(childPosition))); |
|
|
|
} |
|
|
|
|
|
|
|
private void showPostsLayoutPreferences() { |
|
|
|
final PostsLayoutPreferencesDialogFragment fragment = new PostsLayoutPreferencesDialogFragment( |
|
|
|
Constants.PREF_PROFILE_POSTS_LAYOUT, |
|
|
|
preferences -> new Handler().postDelayed(() -> binding.postsRecyclerView.setLayoutPreferences(preferences), 200)); |
|
|
|
fragment.show(getChildFragmentManager(), "posts_layout_preferences"); |
|
|
|
} |
|
|
|
} |