Add Posts view to SavedViewerFragment
This commit is contained in:
parent
d9c30c99b7
commit
ab4306ac0d
@ -0,0 +1,71 @@
|
||||
package awais.instagrabber.asyncs;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.customviews.helpers.PostFetcher;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.enums.PostItemType;
|
||||
import awais.instagrabber.webservices.ProfileService;
|
||||
import awais.instagrabber.webservices.ProfileService.SavedPostsFetchResponse;
|
||||
import awais.instagrabber.webservices.ServiceCallback;
|
||||
|
||||
public class SavedPostFetchService implements PostFetcher.PostFetchService {
|
||||
private final ProfileService profileService;
|
||||
private final String profileId;
|
||||
private final PostItemType type;
|
||||
|
||||
private String nextMaxId;
|
||||
private boolean moreAvailable;
|
||||
|
||||
public SavedPostFetchService(final String profileId, final PostItemType type) {
|
||||
this.profileId = profileId;
|
||||
this.type = type;
|
||||
profileService = ProfileService.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch(final FetchListener<List<FeedModel>> fetchListener) {
|
||||
final ServiceCallback<SavedPostsFetchResponse> callback = new ServiceCallback<SavedPostsFetchResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final SavedPostsFetchResponse result) {
|
||||
if (result == null) return;
|
||||
nextMaxId = result.getNextMaxId();
|
||||
moreAvailable = result.isMoreAvailable();
|
||||
if (fetchListener != null) {
|
||||
fetchListener.onResult(result.getItems());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
// Log.e(TAG, "onFailure: ", t);
|
||||
if (fetchListener != null) {
|
||||
fetchListener.onFailure(t);
|
||||
}
|
||||
}
|
||||
};
|
||||
switch (type) {
|
||||
case LIKED:
|
||||
profileService.fetchLiked(nextMaxId, callback);
|
||||
break;
|
||||
case TAGGED:
|
||||
profileService.fetchTagged(profileId, nextMaxId, callback);
|
||||
break;
|
||||
case SAVED:
|
||||
default:
|
||||
profileService.fetchSaved(nextMaxId, callback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
nextMaxId = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNextPage() {
|
||||
return moreAvailable;
|
||||
}
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
package awais.instagrabber.customviews;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
|
||||
public final class RemixDrawerLayout extends MouseDrawer implements MouseDrawer.DrawerListener {
|
||||
private final FrameLayout frameLayout;
|
||||
private View drawerView;
|
||||
private RecyclerView highlightsList, feedPosts, feedStories;
|
||||
private float startX;
|
||||
|
||||
public RemixDrawerLayout(@NonNull final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public RemixDrawerLayout(@NonNull final Context context, @Nullable final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public RemixDrawerLayout(@NonNull final Context context, @Nullable final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
super.setDrawerElevation(getDrawerElevation());
|
||||
|
||||
addDrawerListener(this);
|
||||
|
||||
frameLayout = new FrameLayout(context);
|
||||
frameLayout.setPadding(0, 0, 0, 0);
|
||||
super.addView(frameLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(@NonNull final View child, final ViewGroup.LayoutParams params) {
|
||||
child.setLayoutParams(params);
|
||||
addView(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(@NonNull final View child) {
|
||||
if (child.getTag() != null) super.addView(child);
|
||||
else frameLayout.addView(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(@NonNull final MotionEvent ev) {
|
||||
final float x = ev.getX();
|
||||
final float y = ev.getY();
|
||||
|
||||
// another one of my own weird hack thingies to make this app work
|
||||
if (feedPosts == null) feedPosts = findViewById(R.id.feedPosts);
|
||||
if (feedPosts != null) {
|
||||
for (int i = 0; i < feedPosts.getChildCount(); ++i) {
|
||||
final View viewHolder = feedPosts.getChildAt(i);
|
||||
final View mediaList = viewHolder.findViewById(R.id.media_list);
|
||||
if (mediaList instanceof ViewPager) {
|
||||
final ViewPager viewPager = (ViewPager) mediaList;
|
||||
|
||||
final Rect rect = new Rect();
|
||||
viewPager.getGlobalVisibleRect(rect);
|
||||
|
||||
final boolean touchIsInMediaList = rect.contains((int) x, (int) y);
|
||||
if (touchIsInMediaList) {
|
||||
final PagerAdapter adapter = viewPager.getAdapter();
|
||||
final int count = adapter != null ? adapter.getCount() : 0;
|
||||
if (count < 1 || viewPager.getCurrentItem() != count - 1) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// thanks to Fede @ https://stackoverflow.com/questions/6920137/android-viewpager-and-horizontalscrollview/7258579#7258579
|
||||
if (highlightsList == null) highlightsList = findViewById(R.id.highlightsList);
|
||||
if (highlightsList != null) {
|
||||
final Boolean result = handleHorizontalRecyclerView(ev, highlightsList);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (feedStories == null) feedStories = findViewById(R.id.feedStories);
|
||||
if (feedStories != null) {
|
||||
final Boolean result = handleHorizontalRecyclerView(ev, feedStories);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
private Boolean handleHorizontalRecyclerView(@NonNull final MotionEvent ev, final RecyclerView view) {
|
||||
final float x = ev.getX();
|
||||
final float y = ev.getY();
|
||||
final boolean touchIsInRecycler = x >= view.getLeft() && x < view.getRight()
|
||||
&& y >= view.getTop() && view.getBottom() > y;
|
||||
|
||||
if (touchIsInRecycler) {
|
||||
final int action = ev.getActionMasked();
|
||||
|
||||
if (action == MotionEvent.ACTION_CANCEL) return super.onInterceptTouchEvent(ev);
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) startX = x;
|
||||
else if (action == MotionEvent.ACTION_MOVE) {
|
||||
final int scrollRange = view.computeHorizontalScrollRange();
|
||||
final int scrollOffset = view.computeHorizontalScrollOffset();
|
||||
final boolean scrollable = scrollRange > view.getWidth();
|
||||
final boolean draggingFromRight = startX > x;
|
||||
|
||||
if (scrollOffset < 1) {
|
||||
if (!scrollable) return super.onInterceptTouchEvent(ev);
|
||||
else if (!draggingFromRight) return super.onInterceptTouchEvent(ev);
|
||||
} else if (scrollable && draggingFromRight && scrollRange - scrollOffset == view.computeHorizontalScrollExtent()) {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawerSlide(@NonNull final View view, @EdgeGravity final int gravity, final float slideOffset) {
|
||||
drawerView = view;
|
||||
final int absHorizGravity = getDrawerViewAbsoluteGravity(GravityCompat.START);
|
||||
final int childAbsGravity = getDrawerViewAbsoluteGravity(drawerView);
|
||||
|
||||
final Window window = getActivity(getContext()).getWindow();
|
||||
final boolean isRtl = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
|
||||
|| window.getDecorView().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
|
||||
|| getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
|
||||
|
||||
final int drawerViewWidth = drawerView.getWidth();
|
||||
|
||||
// for (int i = 0; i < frameLayout.getChildCount(); i++) {
|
||||
// final View child = frameLayout.getChildAt(i);
|
||||
//
|
||||
// final boolean isLeftDrawer = isRtl == (childAbsGravity != absHorizGravity);
|
||||
// float width = isLeftDrawer ? drawerViewWidth : -drawerViewWidth;
|
||||
//
|
||||
// child.setX(width * slideOffset);
|
||||
// }
|
||||
|
||||
final boolean isLeftDrawer = isRtl == (childAbsGravity != absHorizGravity);
|
||||
float width = isLeftDrawer ? drawerViewWidth : -drawerViewWidth;
|
||||
|
||||
frameLayout.setX(width * (isRtl ? -slideOffset : slideOffset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openDrawer(@NonNull final View drawerView, final boolean animate) {
|
||||
super.openDrawer(drawerView, animate);
|
||||
post(() -> onDrawerSlide(drawerView, Gravity.NO_GRAVITY, isDrawerOpen(drawerView) ? 1f : 0f));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(final Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
if (drawerView != null) onDrawerSlide(drawerView, Gravity.NO_GRAVITY, isDrawerOpen(drawerView) ? 1f : 0f);
|
||||
}
|
||||
|
||||
private static Activity getActivity(final Context context) {
|
||||
if (context != null) {
|
||||
if (context instanceof Activity) return (Activity) context;
|
||||
if (context instanceof ContextWrapper)
|
||||
return getActivity(((ContextWrapper) context).getBaseContext());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final int getDrawerViewAbsoluteGravity(final int gravity) {
|
||||
return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this)) & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK;
|
||||
}
|
||||
|
||||
final int getDrawerViewAbsoluteGravity(@NonNull final View drawerView) {
|
||||
final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
|
||||
return getDrawerViewAbsoluteGravity(gravity);
|
||||
}
|
||||
}
|
@ -2,81 +2,69 @@ package awais.instagrabber.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.os.Handler;
|
||||
import android.view.ActionMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
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.AppCompatActivity;
|
||||
import androidx.core.content.PermissionChecker;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.PostsAdapter;
|
||||
import awais.instagrabber.asyncs.PostsFetcher;
|
||||
import awais.instagrabber.asyncs.i.iLikedFetcher;
|
||||
import awais.instagrabber.adapters.FeedAdapterV2;
|
||||
import awais.instagrabber.asyncs.SavedPostFetchService;
|
||||
import awais.instagrabber.customviews.PrimaryActionModeCallback;
|
||||
import awais.instagrabber.customviews.helpers.GridAutofitLayoutManager;
|
||||
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.FragmentSavedBinding;
|
||||
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
|
||||
import awais.instagrabber.fragments.main.ProfileFragmentDirections;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.enums.DownloadMethod;
|
||||
import awais.instagrabber.models.PostsLayoutPreferences;
|
||||
import awais.instagrabber.models.enums.PostItemType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awais.instagrabber.viewmodels.PostsViewModel;
|
||||
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 final class SavedViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static AsyncTask<?, ?, ?> currentlyExecuting;
|
||||
private PostsAdapter postsAdapter;
|
||||
private boolean hasNextPage;
|
||||
private static final int STORAGE_PERM_REQUEST_CODE = 8020;
|
||||
|
||||
private FragmentSavedBinding binding;
|
||||
private String username;
|
||||
private String endCursor;
|
||||
private RecyclerLazyLoader lazyLoader;
|
||||
private ArrayList<PostModel> selectedItems = new ArrayList<>();
|
||||
private ActionMode actionMode;
|
||||
private PostsViewModel postsViewModel;
|
||||
private LinearLayout root;
|
||||
private SwipeRefreshLayout root;
|
||||
private AppCompatActivity fragmentActivity;
|
||||
private boolean shouldRefresh = true;
|
||||
private PostItemType type;
|
||||
private String profileId;
|
||||
|
||||
private final ArrayList<PostModel> selectedItems = new ArrayList<>();
|
||||
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
setEnabled(false);
|
||||
remove();
|
||||
if (postsAdapter == null) return;
|
||||
postsAdapter.clearSelection();
|
||||
// if (postsAdapter == null) return;
|
||||
// postsAdapter.clearSelection();
|
||||
}
|
||||
};
|
||||
private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(
|
||||
@ -90,64 +78,112 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
@Override
|
||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_download) {
|
||||
if (postsAdapter == null || username == null) {
|
||||
return false;
|
||||
}
|
||||
final Context context = getContext();
|
||||
if (context == null) return false;
|
||||
DownloadUtils.batchDownload(context,
|
||||
username,
|
||||
DownloadMethod.DOWNLOAD_SAVED,
|
||||
postsAdapter.getSelectedModels());
|
||||
checkAndResetAction();
|
||||
// if (postsAdapter == null || username == null) {
|
||||
// return false;
|
||||
// }
|
||||
// final Context context = getContext();
|
||||
// if (context == null) return false;
|
||||
// DownloadUtils.batchDownload(context,
|
||||
// username,
|
||||
// DownloadMethod.DOWNLOAD_SAVED,
|
||||
// postsAdapter.getSelectedModels());
|
||||
// checkAndResetAction();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() {
|
||||
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
|
||||
@Override
|
||||
public void onResult(final List<PostModel> result) {
|
||||
final List<PostModel> current = postsViewModel.getList().getValue();
|
||||
if (result != null && !result.isEmpty()) {
|
||||
if (current == null) {
|
||||
postsViewModel.getList().postValue(result);
|
||||
} else {
|
||||
final List<PostModel> currentCopy = new ArrayList<>(current);
|
||||
currentCopy.addAll(result);
|
||||
postsViewModel.getList().postValue(currentCopy);
|
||||
}
|
||||
binding.mainPosts.post(() -> {
|
||||
binding.mainPosts.setNestedScrollingEnabled(true);
|
||||
binding.mainPosts.setVisibility(View.VISIBLE);
|
||||
});
|
||||
public void onPostClick(final FeedModel feedModel, final View profilePicView, final View mainPostImage) {
|
||||
openPostDialog(feedModel, profilePicView, mainPostImage, -1);
|
||||
}
|
||||
|
||||
final PostModel model = !result.isEmpty() ? result.get(result.size() - 1) : null;
|
||||
if (model != null) {
|
||||
endCursor = model.getEndCursor();
|
||||
hasNextPage = model.hasNextPage();
|
||||
if (hasNextPage) {
|
||||
fetchPosts();
|
||||
} else {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
model.setPageCursor(false, null);
|
||||
}
|
||||
} else if (current == null) {
|
||||
final Context context = getContext();
|
||||
if (context == null) return;
|
||||
Toast.makeText(context, R.string.empty_list, Toast.LENGTH_SHORT).show();
|
||||
NavHostFragment.findNavController(SavedViewerFragment.this).popBackStack();
|
||||
@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 = ProfileFragmentDirections.actionGlobalCommentsViewerFragment(
|
||||
feedModel.getShortCode(),
|
||||
feedModel.getPostId(),
|
||||
feedModel.getProfileModel().getId()
|
||||
);
|
||||
NavHostFragment.findNavController(SavedViewerFragment.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;
|
||||
}
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHashtagClick(final String hashtag) {
|
||||
final NavDirections action = ProfileFragmentDirections.actionGlobalHashTagFragment(hashtag);
|
||||
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationClick(final FeedModel feedModel) {
|
||||
final NavDirections action = ProfileFragmentDirections.actionGlobalLocationFragment(feedModel.getLocationId());
|
||||
NavHostFragment.findNavController(SavedViewerFragment.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 Observer<List<PostModel>> listObserver;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (AppCompatActivity) getActivity();
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -164,22 +200,34 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
if (!shouldRefresh) return;
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
init();
|
||||
shouldRefresh = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.saved_viewer_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||
if (item.getItemId() == R.id.layout) {
|
||||
showPostsLayoutPreferences();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setTitle();
|
||||
observeData();
|
||||
}
|
||||
|
||||
private void observeData() {
|
||||
postsViewModel = new ViewModelProvider(this).get(PostsViewModel.class);
|
||||
postsViewModel.getList().removeObserver(listObserver);
|
||||
if (postsAdapter != null) {
|
||||
postsViewModel.getList().observe(getViewLifecycleOwner(), listObserver);
|
||||
}
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
binding.posts.refresh();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
@ -189,122 +237,79 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
username = fragmentArgs.getUsername();
|
||||
profileId = fragmentArgs.getProfileId();
|
||||
type = fragmentArgs.getType();
|
||||
setTitle();
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
// autoloadPosts = Utils.settingsHelper.getBoolean(AUTOLOAD_POSTS);
|
||||
binding.mainPosts.setNestedScrollingEnabled(false);
|
||||
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 = postModels.get(0).getPostId();
|
||||
final boolean isId = postId != null;
|
||||
final String[] idsOrShortCodes = new String[postModels.size()];
|
||||
for (int i = 0; i < postModels.size(); i++) {
|
||||
final PostModel tempPostModel = postModels.get(i);
|
||||
final String tempId = tempPostModel.getPostId();
|
||||
final String finalPostId = type == PostItemType.LIKED ? tempId.substring(0, tempId.indexOf("_")) : tempId;
|
||||
idsOrShortCodes[i] = isId ? finalPostId
|
||||
: tempPostModel.getShortCode();
|
||||
}
|
||||
final NavDirections action = ProfileFragmentDirections.actionGlobalPostViewFragment(
|
||||
position,
|
||||
idsOrShortCodes,
|
||||
isId);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
}, (model, position) -> {
|
||||
if (!postsAdapter.isSelecting()) {
|
||||
checkAndResetAction();
|
||||
return true;
|
||||
}
|
||||
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
||||
if (onBackPressedCallback.isEnabled()) return true;
|
||||
actionMode = fragmentActivity.startActionMode(multiSelectAction);
|
||||
final String title = getString(R.string.number_selected, 1);
|
||||
actionMode.setTitle(title);
|
||||
onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
||||
return true;
|
||||
});
|
||||
binding.mainPosts.setAdapter(postsAdapter);
|
||||
listObserver = list -> postsAdapter.submitList(list);
|
||||
observeData();
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (hasNextPage) {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
fetchPosts();
|
||||
endCursor = null;
|
||||
}
|
||||
});
|
||||
binding.mainPosts.addOnScrollListener(lazyLoader);
|
||||
fetchPosts();
|
||||
setupPosts();
|
||||
// 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 = postModels.get(0).getPostId();
|
||||
// final boolean isId = postId != null;
|
||||
// final String[] idsOrShortCodes = new String[postModels.size()];
|
||||
// for (int i = 0; i < postModels.size(); i++) {
|
||||
// final PostModel tempPostModel = postModels.get(i);
|
||||
// final String tempId = tempPostModel.getPostId();
|
||||
// final String finalPostId = type == PostItemType.LIKED ? tempId.substring(0, tempId.indexOf("_")) : tempId;
|
||||
// idsOrShortCodes[i] = isId ? finalPostId
|
||||
// : tempPostModel.getShortCode();
|
||||
// }
|
||||
// final NavDirections action = ProfileFragmentDirections.actionGlobalPostViewFragment(
|
||||
// position,
|
||||
// idsOrShortCodes,
|
||||
// isId);
|
||||
// NavHostFragment.findNavController(this).navigate(action);
|
||||
// }, (model, position) -> {
|
||||
// if (!postsAdapter.isSelecting()) {
|
||||
// checkAndResetAction();
|
||||
// return true;
|
||||
// }
|
||||
// final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
||||
// if (onBackPressedCallback.isEnabled()) return true;
|
||||
// actionMode = fragmentActivity.startActionMode(multiSelectAction);
|
||||
// final String title = getString(R.string.number_selected, 1);
|
||||
// actionMode.setTitle(title);
|
||||
// onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
||||
// return true;
|
||||
// });
|
||||
}
|
||||
|
||||
private void fetchPosts() {
|
||||
stopCurrentExecutor();
|
||||
final AsyncTask<Void, Void, List<PostModel>> asyncTask;
|
||||
private void setupPosts() {
|
||||
binding.posts.setViewModelStoreOwner(this)
|
||||
.setLifeCycleOwner(this)
|
||||
.setPostFetchService(new SavedPostFetchService(profileId, type))
|
||||
.setLayoutPreferences(PostsLayoutPreferences.fromJson(settingsHelper.getString(getPostsLayoutPreferenceKey())))
|
||||
.addFetchStatusChangeListener(fetching -> updateSwipeRefreshState())
|
||||
.setFeedItemCallback(feedItemCallback)
|
||||
.init();
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getPostsLayoutPreferenceKey() {
|
||||
switch (type) {
|
||||
case LIKED:
|
||||
asyncTask = new iLikedFetcher(endCursor, postsFetchListener);
|
||||
break;
|
||||
case SAVED:
|
||||
return Constants.PREF_LIKED_POSTS_LAYOUT;
|
||||
case TAGGED:
|
||||
if (TextUtils.isEmpty(profileId)) return;
|
||||
asyncTask = new PostsFetcher(profileId, type, endCursor, postsFetchListener);
|
||||
break;
|
||||
return Constants.PREF_TAGGED_POSTS_LAYOUT;
|
||||
case SAVED:
|
||||
default:
|
||||
return;
|
||||
return Constants.PREF_SAVED_POSTS_LAYOUT;
|
||||
}
|
||||
currentlyExecuting = asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
if (lazyLoader != null) lazyLoader.resetState();
|
||||
stopCurrentExecutor();
|
||||
endCursor = null;
|
||||
postsViewModel.getList().postValue(Collections.emptyList());
|
||||
selectedItems.clear();
|
||||
if (postsAdapter != null) {
|
||||
// postsAdapter.isSelecting = false;
|
||||
postsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
fetchPosts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED && selectedItems.size() > 0) {
|
||||
final Context context = getContext();
|
||||
if (context == null) return;
|
||||
DownloadUtils.batchDownload(context, null, DownloadMethod.DOWNLOAD_SAVED, selectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopCurrentExecutor() {
|
||||
if (currentlyExecuting != null) {
|
||||
try {
|
||||
currentlyExecuting.cancel(true);
|
||||
} catch (final Exception e) {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.MAIN_HELPER, "stopCurrentExecutor");
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// final Context context = getContext();
|
||||
// if (context == null) return;
|
||||
// DownloadUtils.batchDownload(context, null, DownloadMethod.DOWNLOAD_SAVED, selectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,9 +318,6 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
if (actionBar == null) return;
|
||||
final int titleRes;
|
||||
switch (type) {
|
||||
case SAVED:
|
||||
titleRes = R.string.saved;
|
||||
break;
|
||||
case LIKED:
|
||||
titleRes = R.string.liked;
|
||||
break;
|
||||
@ -323,12 +325,74 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
|
||||
titleRes = R.string.tagged;
|
||||
break;
|
||||
default:
|
||||
return; // no other types supported in this view
|
||||
case SAVED:
|
||||
titleRes = R.string.saved;
|
||||
break;
|
||||
}
|
||||
actionBar.setTitle(titleRes);
|
||||
actionBar.setSubtitle(username);
|
||||
}
|
||||
|
||||
private void updateSwipeRefreshState() {
|
||||
binding.swipeRefreshLayout.setRefreshing(binding.posts.isFetching());
|
||||
}
|
||||
|
||||
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 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 showPostsLayoutPreferences() {
|
||||
final PostsLayoutPreferencesDialogFragment fragment = new PostsLayoutPreferencesDialogFragment(
|
||||
getPostsLayoutPreferenceKey(),
|
||||
preferences -> new Handler().postDelayed(() -> binding.posts.setLayoutPreferences(preferences), 200));
|
||||
fragment.show(getChildFragmentManager(), "posts_layout_preferences");
|
||||
}
|
||||
|
||||
private boolean checkAndResetAction() {
|
||||
if (!onBackPressedCallback.isEnabled() && actionMode == null) {
|
||||
return false;
|
||||
|
@ -14,4 +14,13 @@ public interface ProfileRepository {
|
||||
|
||||
@GET("/graphql/query/")
|
||||
Call<String> fetch(@QueryMap Map<String, String> queryMap);
|
||||
|
||||
@GET("/api/v1/feed/saved/")
|
||||
Call<String> fetchSaved(@QueryMap Map<String, String> queryParams);
|
||||
|
||||
@GET("/api/v1/feed/liked/")
|
||||
Call<String> fetchLiked(@QueryMap Map<String, String> queryParams);
|
||||
|
||||
@GET("/api/v1/usertags/{profileId}/feed/")
|
||||
Call<String> fetchTagged(@Path("profileId") final String profileId, @QueryMap Map<String, String> queryParams);
|
||||
}
|
||||
|
@ -92,4 +92,7 @@ public final class Constants {
|
||||
public static final String PREF_TOPIC_POSTS_LAYOUT = "topic_posts_layout";
|
||||
public static final String PREF_HASHTAG_POSTS_LAYOUT = "hashtag_posts_layout";
|
||||
public static final String PREF_LOCATION_POSTS_LAYOUT = "location_posts_layout";
|
||||
public static final String PREF_LIKED_POSTS_LAYOUT = "liked_posts_layout";
|
||||
public static final String PREF_TAGGED_POSTS_LAYOUT = "tagged_posts_layout";
|
||||
public static final String PREF_SAVED_POSTS_LAYOUT = "saved_posts_layout";
|
||||
}
|
@ -31,9 +31,12 @@ import static awais.instagrabber.utils.Constants.MUTED_VIDEOS;
|
||||
import static awais.instagrabber.utils.Constants.PREF_DARK_THEME;
|
||||
import static awais.instagrabber.utils.Constants.PREF_HASHTAG_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_LIGHT_THEME;
|
||||
import static awais.instagrabber.utils.Constants.PREF_LIKED_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_LOCATION_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_PROFILE_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_SAVED_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_TAGGED_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREF_TOPIC_POSTS_LAYOUT;
|
||||
import static awais.instagrabber.utils.Constants.PREV_INSTALL_VERSION;
|
||||
import static awais.instagrabber.utils.Constants.SHOW_QUICK_ACCESS_DIALOG;
|
||||
@ -119,7 +122,8 @@ public final class SettingsHelper {
|
||||
@StringDef(
|
||||
{APP_LANGUAGE, APP_THEME, COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION, CUSTOM_DATE_TIME_FORMAT,
|
||||
DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME, PREF_POSTS_LAYOUT, PREF_PROFILE_POSTS_LAYOUT,
|
||||
PREF_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT, PREF_LOCATION_POSTS_LAYOUT})
|
||||
PREF_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT, PREF_LOCATION_POSTS_LAYOUT, PREF_LIKED_POSTS_LAYOUT, PREF_TAGGED_POSTS_LAYOUT,
|
||||
PREF_SAVED_POSTS_LAYOUT})
|
||||
public @interface StringSettings {}
|
||||
|
||||
@StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
||||
|
@ -118,7 +118,7 @@ public class DiscoverService extends BaseService {
|
||||
final JSONObject clusterJson = clustersJson.getJSONObject(i);
|
||||
final String id = clusterJson.optString("id");
|
||||
final String title = clusterJson.optString("title");
|
||||
if (id == null || title == null) {
|
||||
if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title)) {
|
||||
continue;
|
||||
}
|
||||
final String type = clusterJson.optString("type");
|
||||
|
@ -4,6 +4,8 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -13,6 +15,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
import awais.instagrabber.models.PostChild;
|
||||
@ -282,4 +285,242 @@ public class ProfileService extends BaseService {
|
||||
}
|
||||
return sliderItems;
|
||||
}
|
||||
|
||||
public void fetchSaved(final String maxId,
|
||||
final ServiceCallback<SavedPostsFetchResponse> callback) {
|
||||
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
|
||||
if (!TextUtils.isEmpty(maxId)) {
|
||||
builder.put("max_id", maxId);
|
||||
}
|
||||
final Call<String> request = repository.fetchSaved(builder.build());
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
try {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
final String body = response.body();
|
||||
if (TextUtils.isEmpty(body)) {
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
final SavedPostsFetchResponse savedPostsFetchResponse = parseSavedPostsResponse(body, true);
|
||||
callback.onSuccess(savedPostsFetchResponse);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse", e);
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
if (callback != null) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void fetchLiked(final String maxId,
|
||||
final ServiceCallback<SavedPostsFetchResponse> callback) {
|
||||
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
|
||||
if (!TextUtils.isEmpty(maxId)) {
|
||||
builder.put("max_id", maxId);
|
||||
}
|
||||
final Call<String> request = repository.fetchLiked(builder.build());
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
try {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
final String body = response.body();
|
||||
if (TextUtils.isEmpty(body)) {
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
final SavedPostsFetchResponse savedPostsFetchResponse = parseSavedPostsResponse(body, false);
|
||||
callback.onSuccess(savedPostsFetchResponse);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse", e);
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
if (callback != null) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void fetchTagged(final String profileId,
|
||||
final String maxId,
|
||||
final ServiceCallback<SavedPostsFetchResponse> callback) {
|
||||
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
|
||||
if (!TextUtils.isEmpty(maxId)) {
|
||||
builder.put("max_id", maxId);
|
||||
}
|
||||
final Call<String> request = repository.fetchTagged(profileId, builder.build());
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
try {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
final String body = response.body();
|
||||
if (TextUtils.isEmpty(body)) {
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
final SavedPostsFetchResponse savedPostsFetchResponse = parseSavedPostsResponse(body, false);
|
||||
callback.onSuccess(savedPostsFetchResponse);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse", e);
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
if (callback != null) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private SavedPostsFetchResponse parseSavedPostsResponse(final String body, final boolean isInMedia) throws JSONException {
|
||||
final JSONObject root = new JSONObject(body);
|
||||
final boolean moreAvailable = root.optBoolean("more_available");
|
||||
final String nextMaxId = root.optString("next_max_id");
|
||||
final int numResults = root.optInt("num_results");
|
||||
final String status = root.optString("status");
|
||||
final JSONArray itemsJson = root.optJSONArray("items");
|
||||
final List<FeedModel> items = parseItems(itemsJson, isInMedia);
|
||||
return new SavedPostsFetchResponse(
|
||||
moreAvailable,
|
||||
nextMaxId,
|
||||
numResults,
|
||||
status,
|
||||
items
|
||||
);
|
||||
}
|
||||
|
||||
private List<FeedModel> parseItems(final JSONArray items, final boolean isInMedia) throws JSONException {
|
||||
if (items == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<FeedModel> feedModels = new ArrayList<>();
|
||||
for (int i = 0; i < items.length(); i++) {
|
||||
final JSONObject itemJson = items.optJSONObject(i);
|
||||
if (itemJson == null) {
|
||||
continue;
|
||||
}
|
||||
final FeedModel feedModel = ResponseBodyUtils.parseItem(isInMedia ? itemJson.optJSONObject("media") : itemJson);
|
||||
if (feedModel != null) {
|
||||
feedModels.add(feedModel);
|
||||
}
|
||||
}
|
||||
return feedModels;
|
||||
}
|
||||
|
||||
public static class SavedPostsFetchResponse {
|
||||
private boolean moreAvailable;
|
||||
private String nextMaxId;
|
||||
private int numResults;
|
||||
private String status;
|
||||
private List<FeedModel> items;
|
||||
|
||||
public SavedPostsFetchResponse(final boolean moreAvailable,
|
||||
final String nextMaxId,
|
||||
final int numResults,
|
||||
final String status,
|
||||
final List<FeedModel> items) {
|
||||
this.moreAvailable = moreAvailable;
|
||||
this.nextMaxId = nextMaxId;
|
||||
this.numResults = numResults;
|
||||
this.status = status;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public boolean isMoreAvailable() {
|
||||
return moreAvailable;
|
||||
}
|
||||
|
||||
public SavedPostsFetchResponse setMoreAvailable(final boolean moreAvailable) {
|
||||
this.moreAvailable = moreAvailable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getNextMaxId() {
|
||||
return nextMaxId;
|
||||
}
|
||||
|
||||
public SavedPostsFetchResponse setNextMaxId(final String nextMaxId) {
|
||||
this.nextMaxId = nextMaxId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getNumResults() {
|
||||
return numResults;
|
||||
}
|
||||
|
||||
public SavedPostsFetchResponse setNumResults(final int numResults) {
|
||||
this.numResults = numResults;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public SavedPostsFetchResponse setStatus(final String status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<FeedModel> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public SavedPostsFetchResponse setItems(final List<FeedModel> items) {
|
||||
this.items = items;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final SavedPostsFetchResponse that = (SavedPostsFetchResponse) o;
|
||||
return moreAvailable == that.moreAvailable &&
|
||||
numResults == that.numResults &&
|
||||
Objects.equals(nextMaxId, that.nextMaxId) &&
|
||||
Objects.equals(status, that.status) &&
|
||||
Objects.equals(items, that.items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(moreAvailable, nextMaxId, numResults, status, items);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SavedPostsFetchResponse{" +
|
||||
"moreAvailable=" + moreAvailable +
|
||||
", nextMaxId='" + nextMaxId + '\'' +
|
||||
", numResults=" + numResults +
|
||||
", status='" + status + '\'' +
|
||||
", items=" + items +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +267,7 @@ public class TagsService extends BaseService {
|
||||
return Objects.hash(moreAvailable, nextMaxId, numResults, status, items);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TagPostsFetchResponse{" +
|
||||
|
@ -1,28 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/swipe_refresh_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context=".fragments.SavedViewerFragment">
|
||||
|
||||
<!--<include-->
|
||||
<!-- android:id="@+id/toolbar"-->
|
||||
<!-- layout="@layout/layout_include_toolbar" />-->
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
<awais.instagrabber.customviews.PostsRecyclerView
|
||||
android:id="@+id/posts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:tag="@android:string/yes">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/mainPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
tools:listitem="@layout/item_post" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</LinearLayout>
|
||||
android:clipToPadding="false" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/feedLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:animateLayoutChanges="true"
|
||||
android:tag="@android:string/yes">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:elevation="0dp">
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|snap|enterAlways">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/feedStories"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:visibility="gone" />
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/feedSwipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/feedPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_feed_photo" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -1,463 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null">
|
||||
|
||||
<!-- for users -->
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|enterAlways">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/infoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@null"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profileInfoText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profileInfo"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/isVerified"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
app:srcCompat="@drawable/verified" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainFullName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textSize="16sp"
|
||||
tools:text="Austin Huang" />
|
||||
</LinearLayout>
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/mainBiography"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profileInfoText"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
tools:text="THE GLORIOUS (step)OWNER OF THIS APP" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/mainUrl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/mainBiography"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="https://austinhuang.me/" />
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/profileActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/mainUrl">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnFollow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/follow"
|
||||
android:textColor="@color/btn_pink_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_pink_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnRestrict"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/restrict"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background" />
|
||||
|
||||
<!-- only for invisible private accounts -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnBlock"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/block"
|
||||
android:textColor="@color/btn_red_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_red_background" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/myActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/profileActions">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnTagged"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/tagged"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
|
||||
<!-- also used as block -->
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnSaved"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/saved"
|
||||
android:textColor="@color/btn_orange_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_orange_background" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnLiked"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="1dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/liked"
|
||||
android:textColor="@color/btn_lightpink_text_color"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_lightpink_background" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/highlightsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/myActions"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profileInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/profile_info_container_bottom_space">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainProfileImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="35\nPosts" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainFollowers"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="68\nFollowers" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainFollowing"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="64\nFollowing" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
<!-- for hashtags -->
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tagInfoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/profile_info_container_bottom_space"
|
||||
android:visibility="gone">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainHashtagImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="?selectableItemBackgroundBorderless" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainTagPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="35\nPosts" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnFollowTag"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="2"
|
||||
android:text="@string/follow"
|
||||
android:textColor="@color/btn_pink_text_color"
|
||||
android:textSize="20sp"
|
||||
app:backgroundTint="@color/btn_pink_background" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
<!-- for locations -->
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/locInfoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@null"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="5dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/locInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/profile_info_container_bottom_space">
|
||||
|
||||
<awais.instagrabber.customviews.CircularImageView
|
||||
android:id="@+id/mainLocationImage"
|
||||
android:layout_width="@dimen/profile_picture_size"
|
||||
android:layout_height="@dimen/profile_picture_size"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="?selectableItemBackgroundBorderless" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/mainLocPostCount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textSize="15sp"
|
||||
tools:text="35\nPosts" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/btnMap"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="2"
|
||||
android:text="@string/map"
|
||||
android:textColor="@color/btn_green_text_color"
|
||||
android:textSize="20sp"
|
||||
app:backgroundTint="@color/btn_green_background" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/locationFullName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locInfo"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textSize="16sp"
|
||||
tools:text="OUR HOUSE" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/locationBiography"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locationFullName"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="IN THE MIDDLE OF OUR STREET" />
|
||||
|
||||
<awais.instagrabber.customviews.RamboTextView
|
||||
android:id="@+id/locationUrl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/locationBiography"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="https://austinhuang.me/" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/mainPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/item_post" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/privatePage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/private_page_margins"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="40dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/privatePage1"
|
||||
android:layout_width="@dimen/private_page_margins"
|
||||
android:layout_height="@dimen/private_page_margins"
|
||||
app:srcCompat="@drawable/lock" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/privatePage2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/priv_acc"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:textSize="28sp" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
9
app/src/main/res/menu/saved_viewer_menu.xml
Normal file
9
app/src/main/res/menu/saved_viewer_menu.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?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">
|
||||
|
||||
<item
|
||||
android:id="@+id/layout"
|
||||
android:title="@string/layout"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
@ -5,6 +5,25 @@
|
||||
android:id="@+id/profile_nav_graph"
|
||||
app:startDestination="@id/profileFragment">
|
||||
|
||||
<include app:graph="@navigation/comments_nav_graph" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_commentsViewerFragment"
|
||||
app:destination="@id/comments_nav_graph">
|
||||
<argument
|
||||
android:name="shortCode"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
<argument
|
||||
android:name="postId"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
<argument
|
||||
android:name="postUserId"
|
||||
app:argType="string"
|
||||
app:nullable="false" />
|
||||
</action>
|
||||
|
||||
<include app:graph="@navigation/hashtag_nav_graph" />
|
||||
|
||||
<action
|
||||
|
Loading…
Reference in New Issue
Block a user