mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	Add Posts view to Location fragment
This commit is contained in:
		
							parent
							
								
									2931f2d3ab
								
							
						
					
					
						commit
						d9c30c99b7
					
				| @ -0,0 +1,56 @@ | ||||
| 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.LocationModel; | ||||
| import awais.instagrabber.webservices.LocationService; | ||||
| import awais.instagrabber.webservices.LocationService.LocationPostsFetchResponse; | ||||
| import awais.instagrabber.webservices.ServiceCallback; | ||||
| 
 | ||||
| public class LocationPostFetchService implements PostFetcher.PostFetchService { | ||||
|     private final LocationService locationService; | ||||
|     private final LocationModel locationModel; | ||||
|     private String nextMaxId; | ||||
|     private boolean moreAvailable; | ||||
| 
 | ||||
|     public LocationPostFetchService(final LocationModel locationModel) { | ||||
|         this.locationModel = locationModel; | ||||
|         locationService = LocationService.getInstance(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void fetch(final FetchListener<List<FeedModel>> fetchListener) { | ||||
|         locationService.fetchPosts(locationModel.getId(), nextMaxId, new ServiceCallback<LocationPostsFetchResponse>() { | ||||
|             @Override | ||||
|             public void onSuccess(final LocationPostsFetchResponse 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); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void reset() { | ||||
|         nextMaxId = null; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean hasNextPage() { | ||||
|         return moreAvailable; | ||||
|     } | ||||
| } | ||||
| @ -44,7 +44,6 @@ import awais.instagrabber.customviews.PrimaryActionModeCallback; | ||||
| import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; | ||||
| import awais.instagrabber.databinding.FragmentHashtagBinding; | ||||
| import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; | ||||
| import awais.instagrabber.fragments.main.FeedFragmentDirections; | ||||
| import awais.instagrabber.models.FeedModel; | ||||
| import awais.instagrabber.models.HashtagModel; | ||||
| import awais.instagrabber.models.PostsLayoutPreferences; | ||||
| @ -183,13 +182,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe | ||||
| 
 | ||||
|         @Override | ||||
|         public void onHashtagClick(final String hashtag) { | ||||
|             final NavDirections action = FeedFragmentDirections.actionGlobalHashTagFragment(hashtag); | ||||
|             final NavDirections action = HashTagFragmentDirections.actionGlobalHashTagFragment(hashtag); | ||||
|             NavHostFragment.findNavController(HashTagFragment.this).navigate(action); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onLocationClick(final FeedModel feedModel) { | ||||
|             final NavDirections action = FeedFragmentDirections.actionGlobalLocationFragment(feedModel.getLocationId()); | ||||
|             final NavDirections action = HashTagFragmentDirections.actionGlobalLocationFragment(feedModel.getLocationId()); | ||||
|             NavHostFragment.findNavController(HashTagFragment.this).navigate(action); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -6,12 +6,15 @@ import android.graphics.Typeface; | ||||
| import android.net.Uri; | ||||
| import android.os.AsyncTask; | ||||
| import android.os.Bundle; | ||||
| import android.os.Handler; | ||||
| import android.text.SpannableStringBuilder; | ||||
| import android.text.style.RelativeSizeSpan; | ||||
| import android.text.style.StyleSpan; | ||||
| import android.util.Log; | ||||
| 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; | ||||
| @ -19,12 +22,12 @@ 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.core.content.PermissionChecker; | ||||
| import androidx.fragment.app.Fragment; | ||||
| import androidx.lifecycle.ViewModelProvider; | ||||
| import androidx.navigation.NavController; | ||||
| import androidx.navigation.NavDirections; | ||||
| import androidx.navigation.fragment.NavHostFragment; | ||||
| import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||||
| @ -32,71 +35,64 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||||
| 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; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.activities.MainActivity; | ||||
| import awais.instagrabber.adapters.PostsAdapter; | ||||
| import awais.instagrabber.adapters.FeedAdapterV2; | ||||
| import awais.instagrabber.asyncs.LocationFetcher; | ||||
| import awais.instagrabber.asyncs.PostsFetcher; | ||||
| import awais.instagrabber.asyncs.LocationPostFetchService; | ||||
| import awais.instagrabber.customviews.PrimaryActionModeCallback; | ||||
| 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.FragmentLocationBinding; | ||||
| import awais.instagrabber.interfaces.FetchListener; | ||||
| import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; | ||||
| import awais.instagrabber.models.FeedModel; | ||||
| import awais.instagrabber.models.LocationModel; | ||||
| import awais.instagrabber.models.PostModel; | ||||
| import awais.instagrabber.models.PostsLayoutPreferences; | ||||
| import awais.instagrabber.models.StoryModel; | ||||
| import awais.instagrabber.models.enums.DownloadMethod; | ||||
| import awais.instagrabber.models.enums.FavoriteType; | ||||
| import awais.instagrabber.models.enums.PostItemType; | ||||
| import awais.instagrabber.utils.Constants; | ||||
| import awais.instagrabber.utils.CookieUtils; | ||||
| import awais.instagrabber.utils.DataBox; | ||||
| import awais.instagrabber.utils.DownloadUtils; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| import awais.instagrabber.viewmodels.PostsViewModel; | ||||
| import awais.instagrabber.webservices.ServiceCallback; | ||||
| import awais.instagrabber.webservices.StoriesService; | ||||
| import awaisomereport.LogCollector; | ||||
| 
 | ||||
| import static androidx.core.content.PermissionChecker.checkSelfPermission; | ||||
| import static awais.instagrabber.utils.DownloadUtils.WRITE_PERMISSION; | ||||
| import static awais.instagrabber.utils.Utils.logCollector; | ||||
| import static awais.instagrabber.utils.Utils.settingsHelper; | ||||
| 
 | ||||
| public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { | ||||
|     private static final String TAG = "LocationFragment"; | ||||
|     private static final int STORAGE_PERM_REQUEST_CODE = 8020; | ||||
| 
 | ||||
|     private MainActivity fragmentActivity; | ||||
|     private FragmentLocationBinding binding; | ||||
|     private NestedCoordinatorLayout root; | ||||
|     private boolean shouldRefresh = true, hasStories = false; | ||||
|     private boolean shouldRefresh = true; | ||||
|     private boolean hasStories = false; | ||||
|     private String locationId; | ||||
|     private LocationModel locationModel; | ||||
|     private PostsViewModel postsViewModel; | ||||
|     private PostsAdapter postsAdapter; | ||||
|     private ActionMode actionMode; | ||||
|     private StoriesService storiesService; | ||||
|     private boolean hasNextPage; | ||||
|     private String endCursor; | ||||
|     private AsyncTask<?, ?, ?> currentlyExecuting; | ||||
|     private boolean isLoggedIn; | ||||
|     private boolean isPullToRefresh; | ||||
|     private boolean storiesFetching; | ||||
| 
 | ||||
|     private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) { | ||||
|         @Override | ||||
|         public void handleOnBackPressed() { | ||||
|             if (postsAdapter == null) { | ||||
|                 setEnabled(false); | ||||
|                 remove(); | ||||
|                 return; | ||||
|             } | ||||
|             postsAdapter.clearSelection(); | ||||
|             // if (postsAdapter == null) { | ||||
|             //     setEnabled(false); | ||||
|             //     remove(); | ||||
|             //     return; | ||||
|             // } | ||||
|             // postsAdapter.clearSelection(); | ||||
|             setEnabled(false); | ||||
|             remove(); | ||||
|         } | ||||
| @ -112,45 +108,130 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|         public boolean onActionItemClicked(final ActionMode mode, | ||||
|                                            final MenuItem item) { | ||||
|             if (item.getItemId() == R.id.action_download) { | ||||
|                 if (postsAdapter == null || locationId == null) { | ||||
|                     return false; | ||||
|                 } | ||||
|                 final Context context = getContext(); | ||||
|                 if (context == null) return false; | ||||
|                 DownloadUtils.batchDownload(context, | ||||
|                                             locationId, | ||||
|                                             DownloadMethod.DOWNLOAD_MAIN, | ||||
|                                             postsAdapter.getSelectedModels()); | ||||
|                 checkAndResetAction(); | ||||
|                 // if (postsAdapter == null || locationId == null) { | ||||
|                 //     return false; | ||||
|                 // } | ||||
|                 // final Context context = getContext(); | ||||
|                 // if (context == null) return false; | ||||
|                 // DownloadUtils.batchDownload(context, | ||||
|                 //                             locationId, | ||||
|                 //                             DownloadMethod.DOWNLOAD_MAIN, | ||||
|                 //                             postsAdapter.getSelectedModels()); | ||||
|                 // checkAndResetAction(); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     }); | ||||
|     private final FetchListener<List<PostModel>> postsFetchListener = new FetchListener<List<PostModel>>() { | ||||
|     // 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) return; | ||||
|     //         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); | ||||
|     //         PostModel model = null; | ||||
|     //         if (!result.isEmpty()) { | ||||
|     //             model = result.get(result.size() - 1); | ||||
|     //         } | ||||
|     //         if (model == null) return; | ||||
|     //         endCursor = model.getEndCursor(); | ||||
|     //         hasNextPage = model.hasNextPage(); | ||||
|     //         model.setPageCursor(false, null); | ||||
|     //     } | ||||
|     // }; | ||||
|     private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() { | ||||
|         @Override | ||||
|         public void onResult(final List<PostModel> result) { | ||||
|             binding.swipeRefreshLayout.setRefreshing(false); | ||||
|             if (result == null) return; | ||||
|             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); | ||||
|         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 = LocationFragmentDirections.actionGlobalCommentsViewerFragment( | ||||
|                     feedModel.getShortCode(), | ||||
|                     feedModel.getPostId(), | ||||
|                     feedModel.getProfileModel().getId() | ||||
|             ); | ||||
|             NavHostFragment.findNavController(LocationFragment.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; | ||||
|             } | ||||
|             postsViewModel.getList().postValue(finalList); | ||||
|             PostModel model = null; | ||||
|             if (!result.isEmpty()) { | ||||
|                 model = result.get(result.size() - 1); | ||||
|             requestPermissions(DownloadUtils.PERMS, STORAGE_PERM_REQUEST_CODE); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onHashtagClick(final String hashtag) { | ||||
|             final NavDirections action = LocationFragmentDirections.actionGlobalHashTagFragment(hashtag); | ||||
|             NavHostFragment.findNavController(LocationFragment.this).navigate(action); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onLocationClick(final FeedModel feedModel) { | ||||
|             final NavDirections action = LocationFragmentDirections.actionGlobalLocationFragment(feedModel.getLocationId()); | ||||
|             NavHostFragment.findNavController(LocationFragment.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); | ||||
|             } | ||||
|             if (model == null) return; | ||||
|             endCursor = model.getEndCursor(); | ||||
|             hasNextPage = model.hasNextPage(); | ||||
|             model.setPageCursor(false, null); | ||||
|             final PostViewV2Fragment fragment = builder | ||||
|                     .setSharedProfilePicElement(profilePicView) | ||||
|                     .setSharedMainPostElement(mainPostImage) | ||||
|                     .build(); | ||||
|             fragment.show(getChildFragmentManager(), "post_view"); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
| @ -159,6 +240,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|         super.onCreate(savedInstanceState); | ||||
|         fragmentActivity = (MainActivity) requireActivity(); | ||||
|         storiesService = StoriesService.getInstance(); | ||||
|         setHasOptionsMenu(true); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
| @ -185,9 +267,8 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
| 
 | ||||
|     @Override | ||||
|     public void onRefresh() { | ||||
|         isPullToRefresh = true; | ||||
|         endCursor = null; | ||||
|         fetchLocationModel(); | ||||
|         binding.posts.refresh(); | ||||
|         fetchStories(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @ -197,13 +278,27 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         if (postsViewModel != null) { | ||||
|             postsViewModel.getList().postValue(Collections.emptyList()); | ||||
|         } | ||||
|     public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) { | ||||
|         inflater.inflate(R.menu.topic_posts_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 onDestroy() { | ||||
|     //     super.onDestroy(); | ||||
|     // if (postsViewModel != null) { | ||||
|     //     postsViewModel.getList().postValue(Collections.emptyList()); | ||||
|     // } | ||||
|     // } | ||||
| 
 | ||||
|     private void init() { | ||||
|         if (getArguments() == null) return; | ||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||
| @ -213,66 +308,73 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|         binding.favChip.setVisibility(View.GONE); | ||||
|         binding.btnMap.setVisibility(View.GONE); | ||||
|         setTitle(); | ||||
|         setupPosts(); | ||||
|         fetchLocationModel(); | ||||
|     } | ||||
| 
 | ||||
|     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 = postModels.get(0).getPostId(); | ||||
|             final boolean isId = postId != null && isLoggedIn; | ||||
|             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 = LocationFragmentDirections.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; | ||||
|         }); | ||||
|         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); | ||||
|         binding.posts.setViewModelStoreOwner(this) | ||||
|                      .setLifeCycleOwner(this) | ||||
|                      .setPostFetchService(new LocationPostFetchService(locationModel)) | ||||
|                      .setLayoutPreferences(PostsLayoutPreferences.fromJson(settingsHelper.getString(Constants.PREF_LOCATION_POSTS_LAYOUT))) | ||||
|                      .addFetchStatusChangeListener(fetching -> updateSwipeRefreshState()) | ||||
|                      .setFeedItemCallback(feedItemCallback) | ||||
|                      .init(); | ||||
|         binding.swipeRefreshLayout.setRefreshing(true); | ||||
|         // 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 = postModels.get(0).getPostId(); | ||||
|         //     final boolean isId = postId != null && isLoggedIn; | ||||
|         //     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 = LocationFragmentDirections.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; | ||||
|         // }); | ||||
|         // 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 fetchLocationModel() { | ||||
| @ -289,34 +391,15 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|             } | ||||
|             setTitle(); | ||||
|             setupLocationDetails(); | ||||
|             fetchPosts(); | ||||
|             setupPosts(); | ||||
|             fetchStories(); | ||||
|             // fetchPosts(); | ||||
|         }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||
|     } | ||||
| 
 | ||||
|     private void setupLocationDetails() { | ||||
|         final String locationId = locationModel.getId(); | ||||
|         binding.swipeRefreshLayout.setRefreshing(true); | ||||
|         if (isLoggedIn) { | ||||
|             storiesService.getUserStory(locationId, | ||||
|                     null, | ||||
|                     true, | ||||
|                     false, | ||||
|                     false, | ||||
|                     new ServiceCallback<List<StoryModel>>() { | ||||
|                         @Override | ||||
|                         public void onSuccess(final List<StoryModel> storyModels) { | ||||
|                             if (storyModels != null && !storyModels.isEmpty()) { | ||||
|                                 binding.mainLocationImage.setStoriesBorder(); | ||||
|                                 hasStories = true; | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         @Override | ||||
|                         public void onFailure(final Throwable t) { | ||||
|                             Log.e(TAG, "Error", t); | ||||
|                         } | ||||
|                     }); | ||||
|         } | ||||
|         // binding.swipeRefreshLayout.setRefreshing(true); | ||||
|         binding.mainLocationImage.setImageURI(locationModel.getSdProfilePic()); | ||||
|         final String postCount = String.valueOf(locationModel.getPostCount()); | ||||
|         final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, | ||||
| @ -405,18 +488,44 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|                 final NavDirections action = LocationFragmentDirections | ||||
|                         .actionLocationFragmentToStoryViewerFragment(-1, null, false, true, locationId, locationModel.getName()); | ||||
|                 NavHostFragment.findNavController(this).navigate(action); | ||||
|                 return; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private void fetchPosts() { | ||||
|         stopCurrentExecutor(); | ||||
|         currentlyExecuting = new PostsFetcher(locationModel.getId(), PostItemType.LOCATION, endCursor, postsFetchListener) | ||||
|                 .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||
|     private void fetchStories() { | ||||
|         if (isLoggedIn) { | ||||
|             storiesFetching = true; | ||||
|             storiesService.getUserStory(locationId, | ||||
|                                         null, | ||||
|                                         true, | ||||
|                                         false, | ||||
|                                         false, | ||||
|                                         new ServiceCallback<List<StoryModel>>() { | ||||
|                                             @Override | ||||
|                                             public void onSuccess(final List<StoryModel> storyModels) { | ||||
|                                                 if (storyModels != null && !storyModels.isEmpty()) { | ||||
|                                                     binding.mainLocationImage.setStoriesBorder(); | ||||
|                                                     hasStories = true; | ||||
|                                                 } | ||||
|                                                 storiesFetching = false; | ||||
|                                             } | ||||
| 
 | ||||
|                                             @Override | ||||
|                                             public void onFailure(final Throwable t) { | ||||
|                                                 Log.e(TAG, "Error", t); | ||||
|                                                 storiesFetching = false; | ||||
|                                             } | ||||
|                                         }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public void stopCurrentExecutor() { | ||||
|     // private void fetchPosts() { | ||||
|     //     stopCurrentExecutor(); | ||||
|     //     currentlyExecuting = new PostsFetcher(locationModel.getId(), PostItemType.LOCATION, endCursor, postsFetchListener) | ||||
|     //             .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | ||||
|     // } | ||||
| 
 | ||||
|     private void stopCurrentExecutor() { | ||||
|         if (currentlyExecuting != null) { | ||||
|             try { | ||||
|                 currentlyExecuting.cancel(true); | ||||
| @ -435,6 +544,59 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void updateSwipeRefreshState() { | ||||
|         binding.swipeRefreshLayout.setRefreshing(binding.posts.isFetching() || storiesFetching); | ||||
|     } | ||||
| 
 | ||||
|     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 boolean checkAndResetAction() { | ||||
|         if (!onBackPressedCallback.isEnabled() && actionMode == null) { | ||||
|             return false; | ||||
| @ -449,4 +611,11 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     private void showPostsLayoutPreferences() { | ||||
|         final PostsLayoutPreferencesDialogFragment fragment = new PostsLayoutPreferencesDialogFragment( | ||||
|                 Constants.PREF_LOCATION_POSTS_LAYOUT, | ||||
|                 preferences -> new Handler().postDelayed(() -> binding.posts.setLayoutPreferences(preferences), 200)); | ||||
|         fragment.show(getChildFragmentManager(), "posts_layout_preferences"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -197,6 +197,12 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O | ||||
|         return super.onOptionsItemSelected(item); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onResume() { | ||||
|         super.onResume(); | ||||
|         fragmentActivity.setToolbar(binding.toolbar); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onRefresh() { | ||||
|         binding.posts.refresh(); | ||||
|  | ||||
| @ -0,0 +1,15 @@ | ||||
| package awais.instagrabber.repositories; | ||||
| 
 | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import retrofit2.Call; | ||||
| import retrofit2.http.GET; | ||||
| import retrofit2.http.Path; | ||||
| import retrofit2.http.QueryMap; | ||||
| 
 | ||||
| public interface LocationRepository { | ||||
| 
 | ||||
|     @GET("/api/v1/feed/location/{location}/") | ||||
|     Call<String> fetchPosts(@Path("location") final String locationId, | ||||
|                             @QueryMap Map<String, String> queryParams); | ||||
| } | ||||
| @ -91,4 +91,5 @@ public final class Constants { | ||||
|     public static final String PREF_PROFILE_POSTS_LAYOUT = "profile_posts_layout"; | ||||
|     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"; | ||||
| } | ||||
| @ -31,6 +31,7 @@ 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_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_TOPIC_POSTS_LAYOUT; | ||||
| @ -118,7 +119,7 @@ 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_TOPIC_POSTS_LAYOUT, PREF_HASHTAG_POSTS_LAYOUT, PREF_LOCATION_POSTS_LAYOUT}) | ||||
|     public @interface StringSettings {} | ||||
| 
 | ||||
|     @StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS, | ||||
|  | ||||
| @ -0,0 +1,213 @@ | ||||
| package awais.instagrabber.webservices; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| import awais.instagrabber.models.FeedModel; | ||||
| import awais.instagrabber.repositories.LocationRepository; | ||||
| import awais.instagrabber.utils.ResponseBodyUtils; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| import retrofit2.Call; | ||||
| import retrofit2.Callback; | ||||
| import retrofit2.Response; | ||||
| import retrofit2.Retrofit; | ||||
| 
 | ||||
| public class LocationService extends BaseService { | ||||
|     private static final String TAG = "LocationService"; | ||||
| 
 | ||||
|     private final LocationRepository repository; | ||||
| 
 | ||||
|     private static LocationService instance; | ||||
| 
 | ||||
|     private LocationService() { | ||||
|         final Retrofit retrofit = getRetrofitBuilder() | ||||
|                 .baseUrl("https://i.instagram.com") | ||||
|                 .build(); | ||||
|         repository = retrofit.create(LocationRepository.class); | ||||
|     } | ||||
| 
 | ||||
|     public static LocationService getInstance() { | ||||
|         if (instance == null) { | ||||
|             instance = new LocationService(); | ||||
|         } | ||||
|         return instance; | ||||
|     } | ||||
| 
 | ||||
|     public void fetchPosts(@NonNull final String locationId, | ||||
|                            final String maxId, | ||||
|                            final ServiceCallback<LocationPostsFetchResponse> callback) { | ||||
|         final ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String>builder(); | ||||
|         if (!TextUtils.isEmpty(maxId)) { | ||||
|             builder.put("max_id", maxId); | ||||
|         } | ||||
|         final Call<String> request = repository.fetchPosts(locationId, 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 LocationPostsFetchResponse tagPostsFetchResponse = parseResponse(body); | ||||
|                     callback.onSuccess(tagPostsFetchResponse); | ||||
|                 } 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 LocationPostsFetchResponse parseResponse(@NonNull final String body) 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); | ||||
|         return new LocationPostsFetchResponse( | ||||
|                 moreAvailable, | ||||
|                 nextMaxId, | ||||
|                 numResults, | ||||
|                 status, | ||||
|                 items | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     private List<FeedModel> parseItems(final JSONArray items) 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(itemJson); | ||||
|             if (feedModel != null) { | ||||
|                 feedModels.add(feedModel); | ||||
|             } | ||||
|         } | ||||
|         return feedModels; | ||||
|     } | ||||
| 
 | ||||
|     public static class LocationPostsFetchResponse { | ||||
|         private boolean moreAvailable; | ||||
|         private String nextMaxId; | ||||
|         private int numResults; | ||||
|         private String status; | ||||
|         private List<FeedModel> items; | ||||
| 
 | ||||
|         public LocationPostsFetchResponse(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 LocationPostsFetchResponse setMoreAvailable(final boolean moreAvailable) { | ||||
|             this.moreAvailable = moreAvailable; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         public String getNextMaxId() { | ||||
|             return nextMaxId; | ||||
|         } | ||||
| 
 | ||||
|         public LocationPostsFetchResponse setNextMaxId(final String nextMaxId) { | ||||
|             this.nextMaxId = nextMaxId; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         public int getNumResults() { | ||||
|             return numResults; | ||||
|         } | ||||
| 
 | ||||
|         public LocationPostsFetchResponse setNumResults(final int numResults) { | ||||
|             this.numResults = numResults; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         public String getStatus() { | ||||
|             return status; | ||||
|         } | ||||
| 
 | ||||
|         public LocationPostsFetchResponse setStatus(final String status) { | ||||
|             this.status = status; | ||||
|             return this; | ||||
|         } | ||||
| 
 | ||||
|         public List<FeedModel> getItems() { | ||||
|             return items; | ||||
|         } | ||||
| 
 | ||||
|         public LocationPostsFetchResponse 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 LocationPostsFetchResponse that = (LocationPostsFetchResponse) 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 "LocationPostsFetchResponse{" + | ||||
|                     "moreAvailable=" + moreAvailable + | ||||
|                     ", nextMaxId='" + nextMaxId + '\'' + | ||||
|                     ", numResults=" + numResults + | ||||
|                     ", status='" + status + '\'' + | ||||
|                     ", items=" + items + | ||||
|                     '}'; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -56,7 +56,6 @@ | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_marginStart="8dp" | ||||
|                     android:layout_marginLeft="8dp" | ||||
|                     android:text="@string/map" | ||||
|                     app:chipBackgroundColor="@null" | ||||
|                     app:chipIcon="@drawable/ic_outline_map_24" | ||||
| @ -72,7 +71,6 @@ | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_marginStart="8dp" | ||||
|                     android:layout_marginLeft="8dp" | ||||
|                     android:text="@string/add_to_favorites" | ||||
|                     app:chipBackgroundColor="@null" | ||||
|                     app:chipIcon="@drawable/ic_outline_star_plus_24" | ||||
| @ -143,16 +141,15 @@ | ||||
|     </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|     <androidx.swiperefreshlayout.widget.SwipeRefreshLayout | ||||
|         android:id="@+id/swipeRefreshLayout" | ||||
|         android:id="@+id/swipe_refresh_layout" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"> | ||||
|         app:layout_behavior="@string/appbar_scrolling_view_behavior"> | ||||
| 
 | ||||
|         <androidx.recyclerview.widget.RecyclerView | ||||
|             android:id="@+id/mainPosts" | ||||
|         <awais.instagrabber.customviews.PostsRecyclerView | ||||
|             android:id="@+id/posts" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:clipToPadding="false" | ||||
|             tools:listitem="@layout/item_post" /> | ||||
|             android:clipToPadding="false" /> | ||||
|     </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> | ||||
| </awais.instagrabber.customviews.helpers.NestedCoordinatorLayout> | ||||
							
								
								
									
										9
									
								
								app/src/main/res/menu/location_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/menu/location_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> | ||||
| @ -47,6 +47,15 @@ | ||||
|             app:nullable="true" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <action | ||||
|         android:id="@+id/action_global_locationFragment" | ||||
|         app:destination="@id/location_nav_graph"> | ||||
|         <argument | ||||
|             android:name="locationId" | ||||
|             app:argType="string" | ||||
|             app:nullable="false" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <fragment | ||||
|         android:id="@+id/hashTagFragment" | ||||
|         android:name="awais.instagrabber.fragments.HashTagFragment" | ||||
|  | ||||
| @ -5,8 +5,6 @@ | ||||
|     android:id="@+id/location_nav_graph" | ||||
|     app:startDestination="@id/locationFragment"> | ||||
| 
 | ||||
|     <!--<include app:graph="@navigation/post_view_nav_graph" />--> | ||||
| 
 | ||||
|     <action | ||||
|         android:id="@+id/action_global_postViewFragment" | ||||
|         app:destination="@id/post_view_nav_graph"> | ||||
| @ -21,6 +19,43 @@ | ||||
|             app:argType="boolean" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <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> | ||||
| 
 | ||||
|     <action | ||||
|         android:id="@+id/action_global_profileFragment" | ||||
|         app:destination="@id/profile_nav_graph"> | ||||
|         <argument | ||||
|             android:name="username" | ||||
|             app:argType="string" | ||||
|             app:nullable="true" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <action | ||||
|         android:id="@+id/action_global_hashTagFragment" | ||||
|         app:destination="@id/hashtag_nav_graph"> | ||||
|         <argument | ||||
|             android:name="hashtag" | ||||
|             app:argType="string" | ||||
|             app:nullable="false" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <fragment | ||||
|         android:id="@+id/locationFragment" | ||||
|         android:name="awais.instagrabber.fragments.LocationFragment" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user