From 6bfb6e1bf35495256da3bab5fa3aab9ed4c57468 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Sun, 15 Nov 2020 03:58:27 +0900 Subject: [PATCH] Put collapsing toolbar layout views in the main layout to improve scroll behaviour. This removes the spaghetti required to make scroll behaviours work. --- .../instagrabber/activities/MainActivity.java | 84 +----- .../asyncs/direct_messages/InboxFetcher.java | 7 +- .../fragments/HashTagFragment.java | 69 +++-- .../fragments/LocationFragment.java | 84 +++--- .../fragments/SavedViewerFragment.java | 43 +-- .../fragments/TopicPostsFragment.java | 4 +- .../DirectMessageInboxFragment.java | 4 +- .../fragments/main/FeedFragment.java | 36 ++- .../fragments/main/ProfileFragment.java | 150 +++++----- .../java/awais/instagrabber/utils/Utils.java | 23 ++ app/src/main/res/layout/activity_main.xml | 8 +- .../layout/fragment_direct_messages_inbox.xml | 4 +- .../fragment_direct_messages_thread.xml | 1 - app/src/main/res/layout/fragment_discover.xml | 25 +- app/src/main/res/layout/fragment_feed.xml | 34 +-- app/src/main/res/layout/fragment_hashtag.xml | 78 +---- app/src/main/res/layout/fragment_location.xml | 139 +-------- app/src/main/res/layout/fragment_profile.xml | 281 +----------------- .../main/res/layout/fragment_topic_posts.xml | 4 +- .../res/layout/layout_hashtag_details.xml | 63 ++++ .../res/layout/layout_location_details.xml | 123 ++++++++ .../res/layout/layout_profile_details.xml | 255 ++++++++++++++++ 22 files changed, 730 insertions(+), 789 deletions(-) create mode 100644 app/src/main/res/layout/layout_hashtag_details.xml create mode 100644 app/src/main/res/layout/layout_location_details.xml create mode 100644 app/src/main/res/layout/layout_profile_details.xml diff --git a/app/src/main/java/awais/instagrabber/activities/MainActivity.java b/app/src/main/java/awais/instagrabber/activities/MainActivity.java index c556eaf3..a7e96e9a 100644 --- a/app/src/main/java/awais/instagrabber/activities/MainActivity.java +++ b/app/src/main/java/awais/instagrabber/activities/MainActivity.java @@ -40,7 +40,6 @@ import androidx.navigation.ui.NavigationUI; import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.bottomnavigation.BottomNavigationView; -import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; @@ -53,7 +52,6 @@ import awais.instagrabber.R; import awais.instagrabber.adapters.SuggestionsAdapter; import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.asyncs.SuggestionsFetcher; -import awais.instagrabber.customviews.helpers.CustomHideBottomViewOnScrollBehavior; import awais.instagrabber.databinding.ActivityMainBinding; import awais.instagrabber.fragments.PostViewV2Fragment; import awais.instagrabber.fragments.main.FeedFragment; @@ -80,29 +78,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage R.id.profileFragment, R.id.discoverFragment, R.id.morePreferencesFragment); - private static final List KEEP_SCROLL_BEHAVIOUR_DESTINATIONS = Arrays.asList( - R.id.directMessagesInboxFragment, - R.id.feedFragment, - R.id.profileFragment, - R.id.discoverFragment, - R.id.morePreferencesFragment, - R.id.settingsPreferencesFragment, - R.id.aboutFragment, - R.id.hashTagFragment, - R.id.locationFragment, - R.id.savedViewerFragment, - R.id.commentsViewerFragment, - R.id.followViewerFragment, - R.id.directMessagesSettingsFragment, - R.id.notificationsViewer, - R.id.themePreferencesFragment, - R.id.favoritesFragment, - R.id.backupPreferencesFragment, - R.id.directMessagesThreadFragment - ); private static final Map NAV_TO_MENU_ID_MAP = new HashMap<>(); - private static final List REMOVE_COLLAPSING_TOOLBAR_SCROLL_DESTINATIONS = ImmutableList.of(R.id.commentsViewerFragment, - R.id.directMessagesThreadFragment); private static final String FIRST_FRAGMENT_GRAPH_INDEX_KEY = "firstFragmentGraphIndex"; private ActivityMainBinding binding; @@ -152,7 +128,6 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage if (savedInstanceState == null) { setupBottomNavigationBar(true); } - setupScrollingListener(); setupSuggestions(); final boolean checkUpdates = settingsHelper.getBoolean(Constants.CHECK_UPDATES); if (checkUpdates) FlavorTown.updateCheck(this); @@ -281,12 +256,6 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage }); } - private void setupScrollingListener() { - final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) binding.bottomNavView.getLayoutParams(); - layoutParams.setBehavior(new CustomHideBottomViewOnScrollBehavior()); - binding.bottomNavView.requestLayout(); - } - private boolean setupSearchView() { final View actionView = searchMenuItem.getActionView(); if (!(actionView instanceof SearchView)) return false; @@ -478,16 +447,6 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage @SuppressLint("RestrictedApi") final Deque backStack = navController.getBackStack(); setupMenu(backStack.size(), destinationId); binding.bottomNavView.setVisibility(SHOW_BOTTOM_VIEW_DESTINATIONS.contains(destinationId) ? View.VISIBLE : View.GONE); - if (KEEP_SCROLL_BEHAVIOUR_DESTINATIONS.contains(destinationId)) { - setScrollingBehaviour(); - } else { - removeScrollingBehaviour(); - } - if (REMOVE_COLLAPSING_TOOLBAR_SCROLL_DESTINATIONS.contains(destinationId)) { - removeCollapsingToolbarScrollFlags(); - } else { - setCollapsingToolbarScrollFlags(); - } }); } @@ -514,22 +473,6 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage binding.mainNavHost.requestLayout(); } - private void setCollapsingToolbarScrollFlags() { - final CollapsingToolbarLayout collapsingToolbarLayout = binding.collapsingToolbarLayout; - final AppBarLayout.LayoutParams toolbarLayoutLayoutParams = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - toolbarLayoutLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL - | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP - | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - binding.collapsingToolbarLayout.requestLayout(); - } - - private void removeCollapsingToolbarScrollFlags() { - final CollapsingToolbarLayout collapsingToolbarLayout = binding.collapsingToolbarLayout; - final AppBarLayout.LayoutParams toolbarLayoutLayoutParams = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); - toolbarLayoutLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL); - binding.collapsingToolbarLayout.requestLayout(); - } - private void handleIntent(final Intent intent) { if (intent == null) return; final String action = intent.getAction(); @@ -654,23 +597,17 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage return binding.bottomNavView; } - // public void fitSystemWindows(final boolean fit) { - // binding.appBarLayout.setBackground(null); - // binding.appBarLayout.setFitsSystemWindows(fit); - // binding.collapsingToolbarLayout.setBackground(null); - // binding.collapsingToolbarLayout.setFitsSystemWindows(fit); - // final Drawable toolbarBackground = binding.toolbar.getBackground(); - // binding.toolbar.setFitsSystemWindows(fit); - // binding.toolbar.setBackground(null); - // binding.toolbar.setClickable(false); - // } - // - // public int getNavHostContainerId() { - // return binding.mainNavHost.getId(); - // } + public void setCollapsingView(@NonNull final View view) { + binding.collapsingToolbarLayout.addView(view, 0); + } + + public void removeCollapsingView(@NonNull final View view) { + binding.collapsingToolbarLayout.removeView(view); + } public void setToolbar(final Toolbar toolbar) { binding.appBarLayout.setVisibility(View.GONE); + removeScrollingBehaviour(); setSupportActionBar(toolbar); if (currentNavControllerLiveData == null) return; setupNavigation(toolbar, currentNavControllerLiveData.getValue()); @@ -678,8 +615,13 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage public void resetToolbar() { binding.appBarLayout.setVisibility(View.VISIBLE); + setScrollingBehaviour(); setSupportActionBar(binding.toolbar); if (currentNavControllerLiveData == null) return; setupNavigation(binding.toolbar, currentNavControllerLiveData.getValue()); } + + public CollapsingToolbarLayout getCollapsingToolbarView() { + return binding.collapsingToolbarLayout; + } } \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java index 355b3ed1..3f9e98a4 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/direct_messages/InboxFetcher.java @@ -66,9 +66,6 @@ public final class InboxFetcher extends AsyncTask { return null; } JSONObject data = new JSONObject(NetworkUtils.readFromConnection(conn)); - // try (FileWriter fileWriter = new FileWriter(new File("/sdcard/test.json"))) { - // fileWriter.write(data.toString(2)); - // } final long seqId = data.optLong("seq_id"); final int pendingRequestsCount = data.optInt("pending_requests_total"); @@ -94,8 +91,8 @@ public final class InboxFetcher extends AsyncTask { } result = new InboxModel(hasOlder, hasPendingTopRequests, - blendedInboxEnabled, unseenCount, pendingRequestsCount, - seqId, unseenCountTimestamp, oldestCursor, inboxThreadModels); + blendedInboxEnabled, unseenCount, pendingRequestsCount, + seqId, unseenCountTimestamp, oldestCursor, inboxThreadModels); conn.disconnect(); } catch (final Exception e) { diff --git a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java index 14cec315..eb39180f 100644 --- a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java @@ -24,6 +24,7 @@ import androidx.activity.OnBackPressedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.content.PermissionChecker; import androidx.fragment.app.Fragment; import androidx.navigation.NavController; @@ -46,8 +47,8 @@ import awais.instagrabber.asyncs.HashtagFetcher; import awais.instagrabber.asyncs.HashtagPostFetchService; import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.customviews.PrimaryActionModeCallback; -import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; import awais.instagrabber.databinding.FragmentHashtagBinding; +import awais.instagrabber.databinding.LayoutHashtagDetailsBinding; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.models.FeedModel; import awais.instagrabber.models.HashtagModel; @@ -79,7 +80,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe private MainActivity fragmentActivity; private FragmentHashtagBinding binding; - private NestedCoordinatorLayout root; + private CoordinatorLayout root; private boolean shouldRefresh = true; private boolean hasStories = false; private boolean opening = false; @@ -95,6 +96,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe private FeedModel downloadFeedModel; private int downloadChildPosition = -1; private PostsLayoutPreferences layoutPreferences = PostsLayoutPreferences.fromJson(settingsHelper.getString(Constants.PREF_HASHTAG_POSTS_LAYOUT)); + private LayoutHashtagDetailsBinding hashtagDetailsBinding; private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) { @Override @@ -272,10 +274,13 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { if (root != null) { shouldRefresh = false; + fragmentActivity.setCollapsingView(hashtagDetailsBinding.getRoot()); return root; } binding = FragmentHashtagBinding.inflate(inflater, container, false); root = binding.getRoot(); + hashtagDetailsBinding = LayoutHashtagDetailsBinding.inflate(inflater, fragmentActivity.getCollapsingToolbarView(), false); + fragmentActivity.setCollapsingView(hashtagDetailsBinding.getRoot()); return root; } @@ -332,6 +337,14 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe } } + @Override + public void onDestroyView() { + super.onDestroyView(); + if (hashtagDetailsBinding != null) { + fragmentActivity.removeCollapsingView(hashtagDetailsBinding.getRoot()); + } + } + private void init() { if (getArguments() == null) return; final String cookie = settingsHelper.getString(Constants.COOKIE); @@ -374,21 +387,21 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe private void setHashtagDetails() { if (isLoggedIn) { - binding.btnFollowTag.setVisibility(View.VISIBLE); - binding.btnFollowTag.setText(hashtagModel.getFollowing() ? R.string.unfollow : R.string.follow); - binding.btnFollowTag.setChipIconResource(hashtagModel.getFollowing() - ? R.drawable.ic_outline_person_add_disabled_24 - : R.drawable.ic_outline_person_add_24); - binding.btnFollowTag.setOnClickListener(v -> { + hashtagDetailsBinding.btnFollowTag.setVisibility(View.VISIBLE); + hashtagDetailsBinding.btnFollowTag.setText(hashtagModel.getFollowing() ? R.string.unfollow : R.string.follow); + hashtagDetailsBinding.btnFollowTag.setChipIconResource(hashtagModel.getFollowing() + ? R.drawable.ic_outline_person_add_disabled_24 + : R.drawable.ic_outline_person_add_24); + hashtagDetailsBinding.btnFollowTag.setOnClickListener(v -> { final String cookie = settingsHelper.getString(Constants.COOKIE); final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); if (csrfToken != null) { - binding.btnFollowTag.setClickable(false); + hashtagDetailsBinding.btnFollowTag.setClickable(false); if (!hashtagModel.getFollowing()) { tagsService.follow(hashtag.substring(1), csrfToken, new ServiceCallback() { @Override public void onSuccess(final Boolean result) { - binding.btnFollowTag.setClickable(true); + hashtagDetailsBinding.btnFollowTag.setClickable(true); if (!result) { Log.e(TAG, "onSuccess: result is false"); return; @@ -398,7 +411,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onFailure(@NonNull final Throwable t) { - binding.btnFollowTag.setClickable(true); + hashtagDetailsBinding.btnFollowTag.setClickable(true); Log.e(TAG, "onFailure: ", t); final String message = t.getMessage(); Snackbar.make(root, @@ -413,7 +426,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe tagsService.unfollow(hashtag.substring(1), csrfToken, new ServiceCallback() { @Override public void onSuccess(final Boolean result) { - binding.btnFollowTag.setClickable(true); + hashtagDetailsBinding.btnFollowTag.setClickable(true); if (!result) { Log.e(TAG, "onSuccess: result is false"); return; @@ -423,7 +436,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onFailure(@NonNull final Throwable t) { - binding.btnFollowTag.setClickable(true); + hashtagDetailsBinding.btnFollowTag.setClickable(true); Log.e(TAG, "onFailure: ", t); final String message = t.getMessage(); Snackbar.make(root, @@ -436,22 +449,22 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe } }); } else { - binding.btnFollowTag.setVisibility(View.GONE); + hashtagDetailsBinding.btnFollowTag.setVisibility(View.GONE); } final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG); final boolean isFav = favorite != null; - binding.favChip.setVisibility(View.VISIBLE); - binding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24 - : R.drawable.ic_outline_star_plus_24); - binding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites); - binding.favChip.setOnClickListener(v -> { + hashtagDetailsBinding.favChip.setVisibility(View.VISIBLE); + hashtagDetailsBinding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24 + : R.drawable.ic_outline_star_plus_24); + hashtagDetailsBinding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites); + hashtagDetailsBinding.favChip.setOnClickListener(v -> { final DataBox.FavoriteModel fav = Utils.dataBox.getFavorite(hashtag.substring(1), FavoriteType.HASHTAG); final boolean isFavorite = fav != null; final String message; if (isFavorite) { Utils.dataBox.deleteFavorite(hashtag.substring(1), FavoriteType.HASHTAG); - binding.favChip.setText(R.string.add_to_favorites); - binding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24); + hashtagDetailsBinding.favChip.setText(R.string.add_to_favorites); + hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24); message = getString(R.string.removed_from_favs); } else { Utils.dataBox.addOrUpdateFavorite(new DataBox.FavoriteModel( @@ -462,8 +475,8 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe null, new Date() )); - binding.favChip.setText(R.string.favorite_short); - binding.favChip.setChipIconResource(R.drawable.ic_star_check_24); + hashtagDetailsBinding.favChip.setText(R.string.favorite_short); + hashtagDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24); message = getString(R.string.added_to_favs); } final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG); @@ -472,14 +485,14 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe .setAnchorView(fragmentActivity.getBottomNavView()) .show(); }); - binding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic()); + hashtagDetailsBinding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic()); final String postCount = String.valueOf(hashtagModel.getPostCount()); final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, postCount)); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); - binding.mainTagPostCount.setText(span); - binding.mainTagPostCount.setVisibility(View.VISIBLE); - binding.mainHashtagImage.setOnClickListener(v -> { + hashtagDetailsBinding.mainTagPostCount.setText(span); + hashtagDetailsBinding.mainTagPostCount.setVisibility(View.VISIBLE); + hashtagDetailsBinding.mainHashtagImage.setOnClickListener(v -> { if (!hasStories) return; // show stories final NavDirections action = HashTagFragmentDirections @@ -501,7 +514,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onSuccess(final List storyModels) { if (storyModels != null && !storyModels.isEmpty()) { - binding.mainHashtagImage.setStoriesBorder(); + hashtagDetailsBinding.mainHashtagImage.setStoriesBorder(); hasStories = true; } else { hasStories = false; diff --git a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java index 1171b095..f4e2890b 100644 --- a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java @@ -27,6 +27,7 @@ import androidx.activity.OnBackPressedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.content.PermissionChecker; import androidx.fragment.app.Fragment; import androidx.navigation.NavController; @@ -49,8 +50,8 @@ import awais.instagrabber.asyncs.LocationFetcher; import awais.instagrabber.asyncs.LocationPostFetchService; import awais.instagrabber.asyncs.PostFetcher; import awais.instagrabber.customviews.PrimaryActionModeCallback; -import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; import awais.instagrabber.databinding.FragmentLocationBinding; +import awais.instagrabber.databinding.LayoutLocationDetailsBinding; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.models.FeedModel; import awais.instagrabber.models.LocationModel; @@ -79,7 +80,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR private MainActivity fragmentActivity; private FragmentLocationBinding binding; - private NestedCoordinatorLayout root; + private CoordinatorLayout root; private boolean shouldRefresh = true; private boolean hasStories = false; private boolean opening = false; @@ -93,8 +94,8 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR private Set selectedFeedModels; private FeedModel downloadFeedModel; private int downloadChildPosition = -1; - private PostsLayoutPreferences layoutPreferences = PostsLayoutPreferences - .fromJson(settingsHelper.getString(Constants.PREF_LOCATION_POSTS_LAYOUT)); + private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_LOCATION_POSTS_LAYOUT); + private LayoutLocationDetailsBinding locationDetailsBinding; private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) { @Override @@ -273,10 +274,13 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR @Nullable final Bundle savedInstanceState) { if (root != null) { shouldRefresh = false; + fragmentActivity.setCollapsingView(locationDetailsBinding.getRoot()); return root; } binding = FragmentLocationBinding.inflate(inflater, container, false); root = binding.getRoot(); + locationDetailsBinding = LayoutLocationDetailsBinding.inflate(inflater, fragmentActivity.getCollapsingToolbarView(), false); + fragmentActivity.setCollapsingView(locationDetailsBinding.getRoot()); return root; } @@ -333,14 +337,22 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR } } + @Override + public void onDestroyView() { + super.onDestroyView(); + if (locationDetailsBinding != null) { + fragmentActivity.removeCollapsingView(locationDetailsBinding.getRoot()); + } + } + private void init() { if (getArguments() == null) return; final String cookie = settingsHelper.getString(Constants.COOKIE); isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != null; final LocationFragmentArgs fragmentArgs = LocationFragmentArgs.fromBundle(getArguments()); locationId = fragmentArgs.getLocationId(); - binding.favChip.setVisibility(View.GONE); - binding.btnMap.setVisibility(View.GONE); + locationDetailsBinding.favChip.setVisibility(View.GONE); + locationDetailsBinding.btnMap.setVisibility(View.GONE); setTitle(); fetchLocationModel(); } @@ -380,68 +392,68 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR private void setupLocationDetails() { final String locationId = locationModel.getId(); // binding.swipeRefreshLayout.setRefreshing(true); - binding.mainLocationImage.setImageURI(locationModel.getSdProfilePic()); + locationDetailsBinding.mainLocationImage.setImageURI(locationModel.getSdProfilePic()); final String postCount = String.valueOf(locationModel.getPostCount()); final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, postCount)); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); - binding.mainLocPostCount.setText(span); - binding.mainLocPostCount.setVisibility(View.VISIBLE); - binding.locationFullName.setText(locationModel.getName()); + locationDetailsBinding.mainLocPostCount.setText(span); + locationDetailsBinding.mainLocPostCount.setVisibility(View.VISIBLE); + locationDetailsBinding.locationFullName.setText(locationModel.getName()); CharSequence biography = locationModel.getBio(); // binding.locationBiography.setCaptionIsExpandable(true); // binding.locationBiography.setCaptionIsExpanded(true); if (TextUtils.isEmpty(biography)) { - binding.locationBiography.setVisibility(View.GONE); + locationDetailsBinding.locationBiography.setVisibility(View.GONE); } else if (TextUtils.hasMentions(biography)) { - binding.locationBiography.setVisibility(View.VISIBLE); + locationDetailsBinding.locationBiography.setVisibility(View.VISIBLE); biography = TextUtils.getMentionText(biography); - binding.locationBiography.setText(biography, TextView.BufferType.SPANNABLE); + locationDetailsBinding.locationBiography.setText(biography, TextView.BufferType.SPANNABLE); // binding.locationBiography.setMentionClickListener(mentionClickListener); } else { - binding.locationBiography.setVisibility(View.VISIBLE); - binding.locationBiography.setText(biography); - binding.locationBiography.setMentionClickListener(null); + locationDetailsBinding.locationBiography.setVisibility(View.VISIBLE); + locationDetailsBinding.locationBiography.setText(biography); + locationDetailsBinding.locationBiography.setMentionClickListener(null); } if (!locationModel.getGeo().startsWith("geo:0.0,0.0?z=17")) { - binding.btnMap.setVisibility(View.VISIBLE); - binding.btnMap.setOnClickListener(v -> { + locationDetailsBinding.btnMap.setVisibility(View.VISIBLE); + locationDetailsBinding.btnMap.setOnClickListener(v -> { final Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(locationModel.getGeo())); startActivity(intent); }); } else { - binding.btnMap.setVisibility(View.GONE); - binding.btnMap.setOnClickListener(null); + locationDetailsBinding.btnMap.setVisibility(View.GONE); + locationDetailsBinding.btnMap.setOnClickListener(null); } final String url = locationModel.getUrl(); if (TextUtils.isEmpty(url)) { - binding.locationUrl.setVisibility(View.GONE); + locationDetailsBinding.locationUrl.setVisibility(View.GONE); } else if (!url.startsWith("http")) { - binding.locationUrl.setVisibility(View.VISIBLE); - binding.locationUrl.setText(TextUtils.getSpannableUrl("http://" + url)); + locationDetailsBinding.locationUrl.setVisibility(View.VISIBLE); + locationDetailsBinding.locationUrl.setText(TextUtils.getSpannableUrl("http://" + url)); } else { - binding.locationUrl.setVisibility(View.VISIBLE); - binding.locationUrl.setText(TextUtils.getSpannableUrl(url)); + locationDetailsBinding.locationUrl.setVisibility(View.VISIBLE); + locationDetailsBinding.locationUrl.setText(TextUtils.getSpannableUrl(url)); } final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(locationId, FavoriteType.LOCATION); final boolean isFav = favorite != null; - binding.favChip.setVisibility(View.VISIBLE); - binding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24 - : R.drawable.ic_outline_star_plus_24); - binding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites); - binding.favChip.setOnClickListener(v -> { + locationDetailsBinding.favChip.setVisibility(View.VISIBLE); + locationDetailsBinding.favChip.setChipIconResource(isFav ? R.drawable.ic_star_check_24 + : R.drawable.ic_outline_star_plus_24); + locationDetailsBinding.favChip.setText(isFav ? R.string.favorite_short : R.string.add_to_favorites); + locationDetailsBinding.favChip.setOnClickListener(v -> { final DataBox.FavoriteModel fav = Utils.dataBox.getFavorite(locationId, FavoriteType.LOCATION); final boolean isFavorite = fav != null; final String message; if (isFavorite) { Utils.dataBox.deleteFavorite(locationId, FavoriteType.LOCATION); - binding.favChip.setText(R.string.add_to_favorites); - binding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24); + locationDetailsBinding.favChip.setText(R.string.add_to_favorites); + locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24); message = getString(R.string.removed_from_favs); } else { Utils.dataBox.addOrUpdateFavorite(new DataBox.FavoriteModel( @@ -452,8 +464,8 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR locationModel.getSdProfilePic(), new Date() )); - binding.favChip.setText(R.string.favorite_short); - binding.favChip.setChipIconResource(R.drawable.ic_star_check_24); + locationDetailsBinding.favChip.setText(R.string.favorite_short); + locationDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24); message = getString(R.string.added_to_favs); } final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG); @@ -462,7 +474,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR .setAnchorView(fragmentActivity.getBottomNavView()) .show(); }); - binding.mainLocationImage.setOnClickListener(v -> { + locationDetailsBinding.mainLocationImage.setOnClickListener(v -> { if (hasStories) { // show stories final NavDirections action = LocationFragmentDirections @@ -484,7 +496,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR @Override public void onSuccess(final List storyModels) { if (storyModels != null && !storyModels.isEmpty()) { - binding.mainLocationImage.setStoriesBorder(); + locationDetailsBinding.mainLocationImage.setStoriesBorder(); hasStories = true; } storiesFetching = false; diff --git a/app/src/main/java/awais/instagrabber/fragments/SavedViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/SavedViewerFragment.java index 2a2439aa..fbb9f8f7 100644 --- a/app/src/main/java/awais/instagrabber/fragments/SavedViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/SavedViewerFragment.java @@ -45,7 +45,6 @@ import awais.instagrabber.utils.Utils; 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 final int STORAGE_PERM_REQUEST_CODE = 8020; @@ -62,7 +61,7 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL private Set selectedFeedModels; private FeedModel downloadFeedModel; private int downloadChildPosition = -1; - private PostsLayoutPreferences layoutPreferences = PostsLayoutPreferences.fromJson(settingsHelper.getString(getPostsLayoutPreferenceKey())); + private PostsLayoutPreferences layoutPreferences; private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) { @Override @@ -275,46 +274,8 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL username = fragmentArgs.getUsername(); profileId = fragmentArgs.getProfileId(); type = fragmentArgs.getType(); + layoutPreferences = Utils.getPostsLayoutPreferences(getPostsLayoutPreferenceKey()); 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 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 setupPosts() { diff --git a/app/src/main/java/awais/instagrabber/fragments/TopicPostsFragment.java b/app/src/main/java/awais/instagrabber/fragments/TopicPostsFragment.java index 87beef53..720ed3e3 100644 --- a/app/src/main/java/awais/instagrabber/fragments/TopicPostsFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/TopicPostsFragment.java @@ -22,6 +22,7 @@ import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.core.content.PermissionChecker; import androidx.core.graphics.ColorUtils; import androidx.fragment.app.Fragment; @@ -46,7 +47,6 @@ import awais.instagrabber.activities.MainActivity; import awais.instagrabber.adapters.FeedAdapterV2; import awais.instagrabber.asyncs.DiscoverPostFetchService; import awais.instagrabber.customviews.PrimaryActionModeCallback; -import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; import awais.instagrabber.databinding.FragmentTopicPostsBinding; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.fragments.main.DiscoverFragmentDirections; @@ -68,7 +68,7 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O private MainActivity fragmentActivity; private FragmentTopicPostsBinding binding; - private NestedCoordinatorLayout root; + private CoordinatorLayout root; private boolean shouldRefresh = true; private TopicCluster topicCluster; private ActionMode actionMode; diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java index 442296fa..37937d27 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageInboxFragment.java @@ -10,6 +10,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.coordinatorlayout.widget.CoordinatorLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.MutableLiveData; @@ -29,7 +30,6 @@ import java.util.List; import awais.instagrabber.BuildConfig; import awais.instagrabber.adapters.DirectMessageInboxAdapter; import awais.instagrabber.asyncs.direct_messages.InboxFetcher; -import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; import awais.instagrabber.databinding.FragmentDirectMessagesInboxBinding; import awais.instagrabber.interfaces.FetchListener; @@ -41,7 +41,7 @@ public class DirectMessageInboxFragment extends Fragment implements SwipeRefresh private static final String TAG = "DirectMessagesInboxFrag"; private FragmentActivity fragmentActivity; - private NestedCoordinatorLayout root; + private CoordinatorLayout root; private RecyclerView inboxList; private RecyclerLazyLoader lazyLoader; private LinearLayoutManager layoutManager; diff --git a/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java index c75512e2..678cf0d5 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java @@ -28,6 +28,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.common.collect.ImmutableList; import java.util.List; @@ -73,6 +74,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre private FeedModel downloadFeedModel; private int downloadChildPosition = -1; private PostsLayoutPreferences layoutPreferences = PostsLayoutPreferences.fromJson(settingsHelper.getString(Constants.PREF_POSTS_LAYOUT)); + private RecyclerView storiesRecyclerView; private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() { @Override @@ -249,6 +251,9 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre final Bundle savedInstanceState) { if (root != null) { shouldRefresh = false; + if (storiesRecyclerView != null) { + fragmentActivity.setCollapsingView(storiesRecyclerView); + } return root; } binding = FragmentFeedBinding.inflate(inflater, container, false); @@ -279,18 +284,10 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre return super.onOptionsItemSelected(item); } - @Override - public void onPause() { - super.onPause(); - // if (videoAwareRecyclerScroller != null) { - // videoAwareRecyclerScroller.stopPlaying(); - // } - } - @Override public void onResume() { super.onResume(); - binding.feedSwipeRefreshLayout.setRefreshing(false); + updateSwipeRefreshState(); // if (videoAwareRecyclerScroller != null && shouldAutoPlay) { // videoAwareRecyclerScroller.startPlaying(); // } @@ -302,6 +299,14 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre fetchStories(); } + @Override + public void onDestroyView() { + super.onDestroyView(); + if (storiesRecyclerView != null) { + fragmentActivity.removeCollapsingView(storiesRecyclerView); + } + } + @Override public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); @@ -349,8 +354,15 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre }); final Context context = getContext(); if (context == null) return; - binding.feedStoriesRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)); - binding.feedStoriesRecyclerView.setAdapter(feedStoriesAdapter); + storiesRecyclerView = new RecyclerView(context); + final CollapsingToolbarLayout.LayoutParams params = new CollapsingToolbarLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + params.setMargins(0, Utils.getActionBarHeight(context), 0, 0); + storiesRecyclerView.setLayoutParams(params); + storiesRecyclerView.setClipToPadding(false); + storiesRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)); + storiesRecyclerView.setAdapter(feedStoriesAdapter); + fragmentActivity.setCollapsingView(storiesRecyclerView); feedStoriesViewModel.getList().observe(fragmentActivity, feedStoriesAdapter::submitList); fetchStories(); } @@ -387,6 +399,6 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre public void scrollToTop() { binding.feedRecyclerView.smoothScrollToPosition(0); - binding.storiesContainer.setExpanded(true); + // binding.storiesContainer.setExpanded(true); } } diff --git a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java index 41bca0cc..9f8c44ea 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java @@ -60,8 +60,8 @@ import awais.instagrabber.asyncs.UsernameFetcher; import awais.instagrabber.asyncs.direct_messages.CreateThreadAction; import awais.instagrabber.customviews.PrimaryActionModeCallback; import awais.instagrabber.customviews.PrimaryActionModeCallback.CallbacksHelper; -import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout; import awais.instagrabber.databinding.FragmentProfileBinding; +import awais.instagrabber.databinding.LayoutProfileDetailsBinding; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.dialogs.ProfilePicDialogFragment; import awais.instagrabber.fragments.PostViewV2Fragment; @@ -281,6 +281,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe } } }; + private LayoutProfileDetailsBinding profileDetailsBinding; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { @@ -306,21 +307,26 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe final boolean isSame = ("@" + profileModelUsername).equals(this.username); if (isSame) { setUsernameDelayed(); + fragmentActivity.setCollapsingView(profileDetailsBinding.getRoot()); shouldRefresh = false; return root; } } if (username == null || !username.equals(this.username)) { + fragmentActivity.setCollapsingView(profileDetailsBinding.getRoot()); shouldRefresh = true; return root; } } setUsernameDelayed(); + fragmentActivity.setCollapsingView(profileDetailsBinding.getRoot()); shouldRefresh = false; return root; } binding = FragmentProfileBinding.inflate(inflater, container, false); root = binding.getRoot(); + profileDetailsBinding = LayoutProfileDetailsBinding.inflate(inflater, fragmentActivity.getCollapsingToolbarView(), false); + fragmentActivity.setCollapsingView(profileDetailsBinding.getRoot()); return root; } @@ -431,6 +437,14 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe } } + @Override + public void onDestroyView() { + super.onDestroyView(); + if (profileDetailsBinding != null) { + fragmentActivity.removeCollapsingView(profileDetailsBinding.getRoot()); + } + } + @Override public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); @@ -457,11 +471,11 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe setUsernameDelayed(); } if (TextUtils.isEmpty(username) && !isLoggedIn) { - binding.infoContainer.setVisibility(View.GONE); + profileDetailsBinding.infoContainer.setVisibility(View.GONE); binding.swipeRefreshLayout.setEnabled(false); binding.privatePage1.setImageResource(R.drawable.ic_outline_info_24); binding.privatePage2.setText(R.string.no_acc); - final NestedCoordinatorLayout.LayoutParams layoutParams = (NestedCoordinatorLayout.LayoutParams) binding.privatePage.getLayoutParams(); + final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) binding.privatePage.getLayoutParams(); layoutParams.topMargin = 0; binding.privatePage.setLayoutParams(layoutParams); binding.privatePage.setVisibility(View.VISIBLE); @@ -531,7 +545,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe } else { binding.postsRecyclerView.refresh(); } - binding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE); + profileDetailsBinding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE); final String profileId = profileModel.getId(); final String myId = CookieUtils.getUserIdFromCookie(cookie); if (isLoggedIn) { @@ -539,14 +553,14 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe } setupButtons(profileId, myId); if (!profileId.equals(myId)) { - binding.favCb.setVisibility(View.VISIBLE); + profileDetailsBinding.favCb.setVisibility(View.VISIBLE); final boolean isFav = Utils.dataBox.getFavorite(username.substring(1), FavoriteType.USER) != null; - binding.favCb.setChecked(isFav); - binding.favCb.setButtonDrawable(isFav ? R.drawable.ic_star_check_24 : R.drawable.ic_outline_star_plus_24); + profileDetailsBinding.favCb.setChecked(isFav); + profileDetailsBinding.favCb.setButtonDrawable(isFav ? R.drawable.ic_star_check_24 : R.drawable.ic_outline_star_plus_24); } else { - binding.favCb.setVisibility(View.GONE); + profileDetailsBinding.favCb.setVisibility(View.GONE); } - binding.mainProfileImage.setImageURI(profileModel.getHdProfilePic()); + profileDetailsBinding.mainProfileImage.setImageURI(profileModel.getHdProfilePic()); final long followersCount = profileModel.getFollowersCount(); final long followingCount = profileModel.getFollowingCount(); @@ -557,7 +571,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe postCount)); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); - binding.mainPostCount.setText(span); + profileDetailsBinding.mainPostCount.setText(span); final String followersCountStr = String.valueOf(followersCount); final int followersCountStrLen = followersCountStr.length(); @@ -565,7 +579,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe followersCountStr)); span.setSpan(new RelativeSizeSpan(1.2f), 0, followersCountStrLen, 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, followersCountStrLen, 0); - binding.mainFollowers.setText(span); + profileDetailsBinding.mainFollowers.setText(span); final String followingCountStr = String.valueOf(followingCount); final int followingCountStrLen = followingCountStr.length(); @@ -573,68 +587,70 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe followingCountStr)); span.setSpan(new RelativeSizeSpan(1.2f), 0, followingCountStrLen, 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); - binding.mainFollowing.setText(span); + profileDetailsBinding.mainFollowing.setText(span); - binding.mainFullName.setText(TextUtils.isEmpty(profileModel.getName()) ? profileModel.getUsername() - : profileModel.getName()); + profileDetailsBinding.mainFullName.setText(TextUtils.isEmpty(profileModel.getName()) ? profileModel.getUsername() + : profileModel.getName()); final String biography = profileModel.getBiography(); if (!TextUtils.isEmpty(biography)) { - binding.mainBiography.setText(biography); - binding.mainBiography.addOnHashtagListener(autoLinkItem -> { + profileDetailsBinding.mainBiography.setText(biography); + profileDetailsBinding.mainBiography.addOnHashtagListener(autoLinkItem -> { final NavController navController = NavHostFragment.findNavController(this); final Bundle bundle = new Bundle(); final String originalText = autoLinkItem.getOriginalText().trim(); bundle.putString(ARG_HASHTAG, originalText); navController.navigate(R.id.action_global_hashTagFragment, bundle); }); - binding.mainBiography.addOnMentionClickListener(autoLinkItem -> { + profileDetailsBinding.mainBiography.addOnMentionClickListener(autoLinkItem -> { final String originalText = autoLinkItem.getOriginalText().trim(); navigateToProfile(originalText); }); - binding.mainBiography.addOnEmailClickListener(autoLinkItem -> Utils.openEmailAddress(getContext(), - autoLinkItem.getOriginalText().trim())); - binding.mainBiography.addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim())); - binding.mainBiography.setOnLongClickListener(v -> { + profileDetailsBinding.mainBiography.addOnEmailClickListener(autoLinkItem -> Utils.openEmailAddress(getContext(), + autoLinkItem.getOriginalText() + .trim())); + profileDetailsBinding.mainBiography + .addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim())); + profileDetailsBinding.mainBiography.setOnLongClickListener(v -> { if (context != null) Utils.copyText(context, biography); return true; }); } final String url = profileModel.getUrl(); if (TextUtils.isEmpty(url)) { - binding.mainUrl.setVisibility(View.GONE); + profileDetailsBinding.mainUrl.setVisibility(View.GONE); } else { - binding.mainUrl.setVisibility(View.VISIBLE); - binding.mainUrl.setText(url); - binding.mainUrl.addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim())); - binding.mainUrl.setOnLongClickListener(v -> { + profileDetailsBinding.mainUrl.setVisibility(View.VISIBLE); + profileDetailsBinding.mainUrl.setText(url); + profileDetailsBinding.mainUrl.addOnURLClickListener(autoLinkItem -> Utils.openURL(getContext(), autoLinkItem.getOriginalText().trim())); + profileDetailsBinding.mainUrl.setOnLongClickListener(v -> { if (context != null) Utils.copyText(context, url); return true; }); } if (!profileModel.isReallyPrivate()) { - binding.mainFollowing.setClickable(true); - binding.mainFollowers.setClickable(true); + profileDetailsBinding.mainFollowing.setClickable(true); + profileDetailsBinding.mainFollowers.setClickable(true); if (isLoggedIn) { final View.OnClickListener followClickListener = v -> { final NavDirections action = ProfileFragmentDirections.actionProfileFragmentToFollowViewerFragment( profileId, - v == binding.mainFollowers, + v == profileDetailsBinding.mainFollowers, profileModel.getUsername()); NavHostFragment.findNavController(this).navigate(action); }; - binding.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null); - binding.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null); + profileDetailsBinding.mainFollowers.setOnClickListener(followersCount > 0 ? followClickListener : null); + profileDetailsBinding.mainFollowing.setOnClickListener(followingCount > 0 ? followClickListener : null); } binding.swipeRefreshLayout.setRefreshing(true); binding.postsRecyclerView.setVisibility(View.VISIBLE); fetchPosts(); } else { - binding.mainFollowers.setClickable(false); - binding.mainFollowing.setClickable(false); + profileDetailsBinding.mainFollowers.setClickable(false); + profileDetailsBinding.mainFollowing.setClickable(false); binding.swipeRefreshLayout.setRefreshing(false); // error binding.privatePage1.setImageResource(R.drawable.lock); @@ -647,27 +663,27 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe private void setupButtons(final String profileId, final String myId) { if (isLoggedIn) { if (profileId.equals(myId)) { - binding.btnTagged.setVisibility(View.VISIBLE); - binding.btnSaved.setVisibility(View.VISIBLE); - binding.btnLiked.setVisibility(View.VISIBLE); - binding.btnDM.setVisibility(View.GONE); - binding.btnSaved.setText(R.string.saved); + profileDetailsBinding.btnTagged.setVisibility(View.VISIBLE); + profileDetailsBinding.btnSaved.setVisibility(View.VISIBLE); + profileDetailsBinding.btnLiked.setVisibility(View.VISIBLE); + profileDetailsBinding.btnDM.setVisibility(View.GONE); + profileDetailsBinding.btnSaved.setText(R.string.saved); return; } - binding.btnTagged.setVisibility(View.GONE); - binding.btnSaved.setVisibility(View.GONE); - binding.btnLiked.setVisibility(View.GONE); - binding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism? - binding.btnFollow.setVisibility(View.VISIBLE); + profileDetailsBinding.btnTagged.setVisibility(View.GONE); + profileDetailsBinding.btnSaved.setVisibility(View.GONE); + profileDetailsBinding.btnLiked.setVisibility(View.GONE); + profileDetailsBinding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism? + profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE); if (profileModel.getFollowing()) { - binding.btnFollow.setText(R.string.unfollow); - binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); + profileDetailsBinding.btnFollow.setText(R.string.unfollow); + profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); } else if (profileModel.getRequested()) { - binding.btnFollow.setText(R.string.cancel); - binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); + profileDetailsBinding.btnFollow.setText(R.string.cancel); + profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); } else { - binding.btnFollow.setText(R.string.follow); - binding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_24); + profileDetailsBinding.btnFollow.setText(R.string.follow); + profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_24); } if (restrictMenuItem != null) { restrictMenuItem.setVisible(true); @@ -677,7 +693,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe restrictMenuItem.setTitle(R.string.restrict); } } - binding.btnTagged.setVisibility(profileModel.isReallyPrivate() ? View.GONE : View.VISIBLE); + profileDetailsBinding.btnTagged.setVisibility(profileModel.isReallyPrivate() ? View.GONE : View.VISIBLE); if (blockMenuItem != null) { blockMenuItem.setVisible(true); if (profileModel.getBlocked()) { @@ -708,7 +724,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe @Override public void onSuccess(final List storyModels) { if (storyModels != null && !storyModels.isEmpty()) { - binding.mainProfileImage.setStoriesBorder(); + profileDetailsBinding.mainProfileImage.setStoriesBorder(); hasStories = true; } } @@ -722,15 +738,15 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe result -> { highlightsFetching = false; if (result != null) { - binding.highlightsList.setVisibility(View.VISIBLE); + profileDetailsBinding.highlightsList.setVisibility(View.VISIBLE); highlightsViewModel.getList().postValue(result); - } else binding.highlightsList.setVisibility(View.GONE); + } else profileDetailsBinding.highlightsList.setVisibility(View.GONE); }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private void setupCommonListeners() { final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); - binding.btnFollow.setOnClickListener(v -> { + profileDetailsBinding.btnFollow.setOnClickListener(v -> { if (profileModel.getFollowing() || profileModel.getRequested()) { friendshipService.unfollow( userIdFromCookie, @@ -767,29 +783,29 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe }); } }); - binding.btnSaved.setOnClickListener(v -> { + profileDetailsBinding.btnSaved.setOnClickListener(v -> { final NavDirections action = ProfileFragmentDirections.actionProfileFragmentToSavedViewerFragment(profileModel.getUsername(), profileModel.getId(), PostItemType.SAVED); NavHostFragment.findNavController(this).navigate(action); }); - binding.btnLiked.setOnClickListener(v -> { + profileDetailsBinding.btnLiked.setOnClickListener(v -> { final NavDirections action = ProfileFragmentDirections.actionProfileFragmentToSavedViewerFragment(profileModel.getUsername(), profileModel.getId(), PostItemType.LIKED); NavHostFragment.findNavController(this).navigate(action); }); - binding.btnTagged.setOnClickListener(v -> { + profileDetailsBinding.btnTagged.setOnClickListener(v -> { final NavDirections action = ProfileFragmentDirections.actionProfileFragmentToSavedViewerFragment(profileModel.getUsername(), profileModel.getId(), PostItemType.TAGGED); NavHostFragment.findNavController(this).navigate(action); }); - binding.btnDM.setOnClickListener(v -> new CreateThreadAction(cookie, profileModel.getId(), threadId -> { + profileDetailsBinding.btnDM.setOnClickListener(v -> new CreateThreadAction(cookie, profileModel.getId(), threadId -> { final NavDirections action = ProfileFragmentDirections.actionProfileFragmentToDMThreadFragment(threadId, profileModel.getUsername()); NavHostFragment.findNavController(this).navigate(action); }).execute()); - binding.mainProfileImage.setOnClickListener(v -> { + profileDetailsBinding.mainProfileImage.setOnClickListener(v -> { if (!hasStories) { // show profile pic showProfilePicDialog(); @@ -818,7 +834,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe .setNegativeButton(R.string.cancel, null) .show(); }); - binding.favCb.setOnCheckedChangeListener((buttonView, isChecked) -> { + profileDetailsBinding.favCb.setOnCheckedChangeListener((buttonView, isChecked) -> { // do not do anything if state matches the db, as listener is set before profile details are set final String finalUsername = username.startsWith("@") ? username.substring(1) : username; final DataBox.FavoriteModel favorite = Utils.dataBox.getFavorite(finalUsername, FavoriteType.USER); @@ -826,7 +842,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe return; } buttonView.setVisibility(View.GONE); - binding.favProgress.setVisibility(View.VISIBLE); + profileDetailsBinding.favProgress.setVisibility(View.VISIBLE); final String message; if (isChecked) { final DataBox.FavoriteModel model = new DataBox.FavoriteModel( @@ -838,20 +854,20 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe new Date() ); Utils.dataBox.addOrUpdateFavorite(model); - binding.favCb.setButtonDrawable(R.drawable.ic_star_check_24); + profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_star_check_24); message = getString(R.string.added_to_favs); } else { Utils.dataBox.deleteFavorite(finalUsername, FavoriteType.USER); message = getString(R.string.removed_from_favs); - binding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24); + profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24); } final Snackbar snackbar = Snackbar.make(root, message, BaseTransientBottomBar.LENGTH_LONG); snackbar.setAction(R.string.ok, v -> snackbar.dismiss()) .setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE) .setAnchorView(fragmentActivity.getBottomNavView()) .show(); - binding.favProgress.setVisibility(View.GONE); - binding.favCb.setVisibility(View.VISIBLE); + profileDetailsBinding.favProgress.setVisibility(View.GONE); + profileDetailsBinding.favCb.setVisibility(View.VISIBLE); }); } @@ -900,8 +916,8 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe final Context context = getContext(); if (context == null) return; final RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false); - binding.highlightsList.setLayoutManager(layoutManager); - binding.highlightsList.setAdapter(highlightsAdapter); + profileDetailsBinding.highlightsList.setLayoutManager(layoutManager); + profileDetailsBinding.highlightsList.setAdapter(highlightsAdapter); highlightsViewModel.getList().observe(getViewLifecycleOwner(), highlightModels -> highlightsAdapter.submitList(highlightModels)); } diff --git a/app/src/main/java/awais/instagrabber/utils/Utils.java b/app/src/main/java/awais/instagrabber/utils/Utils.java index ee6c06a5..83dbdac4 100755 --- a/app/src/main/java/awais/instagrabber/utils/Utils.java +++ b/app/src/main/java/awais/instagrabber/utils/Utils.java @@ -11,6 +11,7 @@ import android.net.Uri; import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; +import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.webkit.MimeTypeMap; @@ -34,6 +35,7 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import awais.instagrabber.R; +import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.models.enums.FavoriteType; import awaisomereport.LogCollector; @@ -51,6 +53,7 @@ public final class Utils { public static SimpleDateFormat datetimeParser; public static SimpleCache simpleCache; private static int statusBarHeight; + private static int actionBarHeight; public static int convertDpToPx(final float dp) { if (displayMetrics == null) @@ -162,6 +165,17 @@ public final class Utils { return statusBarHeight; } + public static int getActionBarHeight(@NonNull final Context context) { + if (actionBarHeight > 0) { + return actionBarHeight; + } + final TypedValue tv = new TypedValue(); + if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { + actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, displayMetrics); + } + return actionBarHeight; + } + public static void openURL(final Context context, final String url) { if (context == null || TextUtils.isEmpty(url)) { return; @@ -190,4 +204,13 @@ public final class Utils { view.getTop() - view.getHeight() - 4); toast.show(); } + + public static PostsLayoutPreferences getPostsLayoutPreferences(final String layoutPreferenceKey) { + PostsLayoutPreferences layoutPreferences = PostsLayoutPreferences.fromJson(settingsHelper.getString(layoutPreferenceKey)); + if (layoutPreferences == null) { + layoutPreferences = PostsLayoutPreferences.builder().build(); + settingsHelper.putString(layoutPreferenceKey, layoutPreferences.getJson()); + } + return layoutPreferences; + } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ad84f7a4..866770aa 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -20,14 +20,17 @@ android:id="@+id/collapsingToolbarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - app:layout_scrollFlags="scroll|snap|enterAlways" + android:animateLayoutChanges="true" + android:minHeight="?attr/actionBarSize" + app:layout_scrollFlags="scroll|enterAlwaysCollapsed|exitUntilCollapsed" app:titleEnabled="false"> @@ -45,5 +48,6 @@ android:layout_height="wrap_content" android:layout_gravity="bottom" app:labelVisibilityMode="labeled" + app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior" app:menu="@menu/main_bottom_navigation_menu" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_direct_messages_inbox.xml b/app/src/main/res/layout/fragment_direct_messages_inbox.xml index e5a8f69f..a77b7cff 100644 --- a/app/src/main/res/layout/fragment_direct_messages_inbox.xml +++ b/app/src/main/res/layout/fragment_direct_messages_inbox.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/fragment_direct_messages_thread.xml b/app/src/main/res/layout/fragment_direct_messages_thread.xml index dc226234..5248fa19 100644 --- a/app/src/main/res/layout/fragment_direct_messages_thread.xml +++ b/app/src/main/res/layout/fragment_direct_messages_thread.xml @@ -11,7 +11,6 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" - app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_constraintBottom_toTopOf="@id/comment_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/fragment_discover.xml b/app/src/main/res/layout/fragment_discover.xml index ae5b93dd..6636e3bc 100644 --- a/app/src/main/res/layout/fragment_discover.xml +++ b/app/src/main/res/layout/fragment_discover.xml @@ -1,32 +1,11 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_feed.xml b/app/src/main/res/layout/fragment_feed.xml index b50138eb..da5f341f 100644 --- a/app/src/main/res/layout/fragment_feed.xml +++ b/app/src/main/res/layout/fragment_feed.xml @@ -1,28 +1,28 @@ - - + + + + - + + + + - - - + + + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_hashtag.xml b/app/src/main/res/layout/fragment_hashtag.xml index 2861987b..7bd26633 100644 --- a/app/src/main/res/layout/fragment_hashtag.xml +++ b/app/src/main/res/layout/fragment_hashtag.xml @@ -1,84 +1,10 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_location.xml b/app/src/main/res/layout/fragment_location.xml index 669f67d1..7bd26633 100644 --- a/app/src/main/res/layout/fragment_location.xml +++ b/app/src/main/res/layout/fragment_location.xml @@ -1,145 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml index 9680d4d2..5bf6a013 100644 --- a/app/src/main/res/layout/fragment_profile.xml +++ b/app/src/main/res/layout/fragment_profile.xml @@ -1,276 +1,27 @@ - - + + + + + + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_topic_posts.xml b/app/src/main/res/layout/fragment_topic_posts.xml index cc053d9c..4d82bbe3 100644 --- a/app/src/main/res/layout/fragment_topic_posts.xml +++ b/app/src/main/res/layout/fragment_topic_posts.xml @@ -1,5 +1,5 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_hashtag_details.xml b/app/src/main/res/layout/layout_hashtag_details.xml new file mode 100644 index 00000000..56ddc32e --- /dev/null +++ b/app/src/main/res/layout/layout_hashtag_details.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_location_details.xml b/app/src/main/res/layout/layout_location_details.xml new file mode 100644 index 00000000..9176519a --- /dev/null +++ b/app/src/main/res/layout/layout_location_details.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_profile_details.xml b/app/src/main/res/layout/layout_profile_details.xml new file mode 100644 index 00000000..0c46eab4 --- /dev/null +++ b/app/src/main/res/layout/layout_profile_details.xml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file