1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-24 15:47:30 +00:00

remove discover topics

This commit is contained in:
Austin Huang 2021-07-17 11:15:46 -04:00
parent 70570560d7
commit 4641fe27dc
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
4 changed files with 274 additions and 563 deletions

View File

@ -1,393 +0,0 @@
package awais.instagrabber.fragments;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Handler;
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;
import androidx.activity.OnBackPressedCallback;
import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.transition.ChangeBounds;
import androidx.transition.TransitionInflater;
import androidx.transition.TransitionSet;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.imagepipeline.image.ImageInfo;
import com.google.common.collect.ImmutableList;
import java.util.Set;
import awais.instagrabber.R;
import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.FeedAdapterV2;
import awais.instagrabber.asyncs.DiscoverPostFetchService;
import awais.instagrabber.customviews.PrimaryActionModeCallback;
import awais.instagrabber.databinding.FragmentTopicPostsBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.ResponseBodyUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.DiscoverService;
public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = TopicPostsFragment.class.getSimpleName();
private MainActivity fragmentActivity;
private FragmentTopicPostsBinding binding;
private CoordinatorLayout root;
private boolean shouldRefresh = true;
private TopicCluster topicCluster;
private ActionMode actionMode;
private Set<Media> selectedFeedModels;
private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_TOPIC_POSTS_LAYOUT);
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
binding.posts.endSelection();
}
};
private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(
R.menu.multi_select_download_menu, new PrimaryActionModeCallback.CallbacksHelper() {
@Override
public void onDestroy(final ActionMode mode) {
binding.posts.endSelection();
}
@Override
public boolean onActionItemClicked(final ActionMode mode,
final MenuItem item) {
if (item.getItemId() == R.id.action_download) {
if (TopicPostsFragment.this.selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
DownloadUtils.download(context, ImmutableList.copyOf(TopicPostsFragment.this.selectedFeedModels));
binding.posts.endSelection();
return true;
}
return false;
}
});
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel) {
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
final User user = feedModel.getUser();
if (user == null) return;
final NavDirections commentsAction = TopicPostsFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
user.getPk()
);
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(commentsAction);
}
@Override
public void onDownloadClick(final Media feedModel, final int childPosition, final View popupLocation) {
final Context context = getContext();
if (context == null) return;
DownloadUtils.showDownloadDialog(context, feedModel, childPosition, popupLocation);
}
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = TopicPostsFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(action);
}
@Override
public void onLocationClick(final Media feedModel) {
final Location location = feedModel.getLocation();
if (location == null) return;
final NavDirections action = TopicPostsFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(action);
}
@Override
public void onMentionClick(final String mention) {
navigateToProfile(mention.trim());
}
@Override
public void onNameClick(final Media feedModel) {
navigateToProfile("@" + feedModel.getUser().getUsername());
}
@Override
public void onProfilePicClick(final Media feedModel) {
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.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 Media feedModel, final int position) {
try {
final NavDirections action = TopicPostsFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
}
};
private final FeedAdapterV2.SelectionModeCallback selectionModeCallback = new FeedAdapterV2.SelectionModeCallback() {
@Override
public void onSelectionStart() {
if (!onBackPressedCallback.isEnabled()) {
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
onBackPressedCallback.setEnabled(true);
onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
}
if (actionMode == null) {
actionMode = fragmentActivity.startActionMode(multiSelectAction);
}
}
@Override
public void onSelectionChange(final Set<Media> selectedFeedModels) {
final String title = getString(R.string.number_selected, selectedFeedModels.size());
if (actionMode != null) {
actionMode.setTitle(title);
}
TopicPostsFragment.this.selectedFeedModels = selectedFeedModels;
}
@Override
public void onSelectionEnd() {
if (onBackPressedCallback.isEnabled()) {
onBackPressedCallback.setEnabled(false);
onBackPressedCallback.remove();
}
if (actionMode != null) {
actionMode.finish();
actionMode = null;
}
}
};
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragmentActivity = (MainActivity) requireActivity();
final Context context = getContext();
if (context != null) {
final TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeBounds())
.addTransition(TransitionInflater.from(context).inflateTransition(android.R.transition.move))
.setDuration(200);
setSharedElementEnterTransition(transitionSet);
}
postponeEnterTransition();
setHasOptionsMenu(true);
}
@Nullable
@Override
public View onCreateView(@NonNull final LayoutInflater inflater,
@Nullable final ViewGroup container,
@Nullable final Bundle savedInstanceState) {
if (root != null) {
shouldRefresh = false;
return root;
}
binding = FragmentTopicPostsBinding.inflate(inflater, container, false);
root = binding.getRoot();
return root;
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
if (!shouldRefresh) return;
binding.swipeRefreshLayout.setOnRefreshListener(this);
init();
shouldRefresh = false;
}
@Override
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
inflater.inflate(R.menu.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 onResume() {
super.onResume();
fragmentActivity.setToolbar(binding.toolbar, this);
}
@Override
public void onRefresh() {
binding.posts.refresh();
}
@Override
public void onStop() {
super.onStop();
fragmentActivity.resetToolbar(this);
}
private void init() {
if (getArguments() == null) return;
final TopicPostsFragmentArgs fragmentArgs = TopicPostsFragmentArgs.fromBundle(getArguments());
topicCluster = fragmentArgs.getTopicCluster();
setupToolbar(fragmentArgs.getTitleColor(), fragmentArgs.getBackgroundColor());
setupPosts();
}
private void setupToolbar(final int titleColor, final int backgroundColor) {
if (topicCluster == null) {
return;
}
binding.cover.setTransitionName("cover-" + topicCluster.getId());
fragmentActivity.setToolbar(binding.toolbar, this);
binding.collapsingToolbarLayout.setTitle(topicCluster.getTitle());
final int collapsedTitleTextColor = ColorUtils.setAlphaComponent(titleColor, 0xFF);
final int expandedTitleTextColor = ColorUtils.setAlphaComponent(titleColor, 0x99);
binding.collapsingToolbarLayout.setExpandedTitleColor(expandedTitleTextColor);
binding.collapsingToolbarLayout.setCollapsedTitleTextColor(collapsedTitleTextColor);
binding.collapsingToolbarLayout.setContentScrimColor(backgroundColor);
final Drawable navigationIcon = binding.toolbar.getNavigationIcon();
final Drawable overflowIcon = binding.toolbar.getOverflowIcon();
if (navigationIcon != null && overflowIcon != null) {
final Drawable navDrawable = navigationIcon.mutate();
final Drawable overflowDrawable = overflowIcon.mutate();
navDrawable.setAlpha(0xFF);
overflowDrawable.setAlpha(0xFF);
final ArgbEvaluator argbEvaluator = new ArgbEvaluator();
binding.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
final int totalScrollRange = appBarLayout.getTotalScrollRange();
final float current = totalScrollRange + verticalOffset;
final float fraction = current / totalScrollRange;
final int tempColor = (int) argbEvaluator.evaluate(fraction, collapsedTitleTextColor, expandedTitleTextColor);
navDrawable.setColorFilter(tempColor, PorterDuff.Mode.SRC_ATOP);
overflowDrawable.setColorFilter(tempColor, PorterDuff.Mode.SRC_ATOP);
});
}
final GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
new int[]{Color.TRANSPARENT, backgroundColor});
binding.background.setBackground(gd);
setupCover();
}
private void setupCover() {
final String coverUrl = ResponseBodyUtils.getImageUrl(topicCluster.getCoverMedia());
final DraweeController controller = Fresco
.newDraweeControllerBuilder()
.setOldController(binding.cover.getController())
.setUri(coverUrl)
.setControllerListener(new BaseControllerListener<ImageInfo>() {
@Override
public void onFailure(final String id, final Throwable throwable) {
super.onFailure(id, throwable);
startPostponedEnterTransition();
}
@Override
public void onFinalImageSet(final String id,
@Nullable final ImageInfo imageInfo,
@Nullable final Animatable animatable) {
startPostponedEnterTransition();
}
})
.build();
binding.cover.setController(controller);
}
private void setupPosts() {
final DiscoverService.TopicalExploreRequest topicalExploreRequest = new DiscoverService.TopicalExploreRequest();
topicalExploreRequest.setClusterId(topicCluster.getId());
binding.posts.setViewModelStoreOwner(this)
.setLifeCycleOwner(this)
.setPostFetchService(new DiscoverPostFetchService(topicalExploreRequest))
.setLayoutPreferences(layoutPreferences)
.addFetchStatusChangeListener(fetching -> updateSwipeRefreshState())
.setFeedItemCallback(feedItemCallback)
.setSelectionModeCallback(selectionModeCallback)
.init();
binding.swipeRefreshLayout.setRefreshing(true);
}
private void updateSwipeRefreshState() {
AppExecutors.INSTANCE.getMainThread().execute(() -> binding.swipeRefreshLayout.setRefreshing(binding.posts.isFetching())
);
}
private void navigateToProfile(final String username) {
try {
final NavDirections action = TopicPostsFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {
final PostsLayoutPreferencesDialogFragment fragment = new PostsLayoutPreferencesDialogFragment(
Constants.PREF_TOPIC_POSTS_LAYOUT,
preferences -> {
layoutPreferences = preferences;
new Handler().postDelayed(() -> binding.posts.setLayoutPreferences(preferences), 200);
});
fragment.show(getChildFragmentManager(), "posts_layout_preferences");
}
}

View File

@ -1,75 +1,235 @@
package awais.instagrabber.fragments.main; package awais.instagrabber.fragments.main;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.ActionBar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
import androidx.navigation.fragment.FragmentNavigator;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import java.util.Collections; import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.Set;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.activities.MainActivity; import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.DiscoverTopicsAdapter; import awais.instagrabber.adapters.FeedAdapterV2;
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration; import awais.instagrabber.asyncs.DiscoverPostFetchService;
import awais.instagrabber.customviews.PrimaryActionModeCallback;
import awais.instagrabber.databinding.FragmentDiscoverBinding; import awais.instagrabber.databinding.FragmentDiscoverBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.PostItemType;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.discover.TopicCluster; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse;
import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.CoroutineUtilsKt; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import awais.instagrabber.viewmodels.TopicClusterViewModel;
import awais.instagrabber.webservices.DiscoverService; import awais.instagrabber.webservices.DiscoverService;
import awais.instagrabber.webservices.MediaRepository;
import awais.instagrabber.webservices.ServiceCallback; import static awais.instagrabber.utils.Utils.settingsHelper;
import kotlinx.coroutines.Dispatchers;
public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "DiscoverFragment"; private static final String TAG = "DiscoverFragment";
private MainActivity fragmentActivity; private MainActivity fragmentActivity;
private CoordinatorLayout root; private SwipeRefreshLayout root;
private FragmentDiscoverBinding binding; private FragmentDiscoverBinding binding;
private TopicClusterViewModel topicClusterViewModel; private ActionMode actionMode;
private boolean shouldRefresh = true; private boolean isLoggedIn, shouldRefresh = true;
private DiscoverService discoverService; private String keyword;
private MediaRepository mediaRepository; private Set<Media> selectedFeedModels;
private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_TOPIC_POSTS_LAYOUT);
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
binding.posts.endSelection();
}
};
private final PrimaryActionModeCallback multiSelectAction = new PrimaryActionModeCallback(
R.menu.multi_select_download_menu,
new PrimaryActionModeCallback.CallbacksHelper() {
@Override
public void onDestroy(final ActionMode mode) {
binding.posts.endSelection();
}
@Override
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
if (item.getItemId() == R.id.action_download) {
if (selectedFeedModels == null) return false;
final Context context = getContext();
if (context == null) return false;
DownloadUtils.download(context, ImmutableList.copyOf(DiscoverFragment.this.selectedFeedModels));
binding.posts.endSelection();
}
return false;
}
});
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel) {
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
final User user = feedModel.getUser();
if (user == null) return;
try {
final NavDirections commentsAction = ProfileFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
user.getPk()
);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(commentsAction);
} catch (Exception e) {
Log.e(TAG, "onCommentsClick: ", e);
}
}
@Override
public void onDownloadClick(final Media feedModel, final int childPosition, final View popupLocation) {
final Context context = getContext();
if (context == null) return;
DownloadUtils.showDownloadDialog(context, feedModel, childPosition, popupLocation);
}
@Override
public void onHashtagClick(final String hashtag) {
try {
final NavDirections action = ProfileFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
public void onLocationClick(final Media feedModel) {
final Location location = feedModel.getLocation();
if (location == null) return;
try {
final NavDirections action = ProfileFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onLocationClick: ", e);
}
}
@Override
public void onMentionClick(final String mention) {
navigateToProfile(mention.trim());
}
@Override
public void onNameClick(final Media feedModel) {
navigateToProfile("@" + feedModel.getUser().getUsername());
}
@Override
public void onProfilePicClick(final Media feedModel) {
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.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 Media feedModel, final int position) {
try {
final NavDirections action = DiscoverFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
}
};
private final FeedAdapterV2.SelectionModeCallback selectionModeCallback = new FeedAdapterV2.SelectionModeCallback() {
@Override
public void onSelectionStart() {
if (!onBackPressedCallback.isEnabled()) {
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
onBackPressedCallback.setEnabled(true);
onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
}
if (actionMode == null) {
actionMode = fragmentActivity.startActionMode(multiSelectAction);
}
}
@Override
public void onSelectionChange(final Set<Media> selectedFeedModels) {
final String title = getString(R.string.number_selected, selectedFeedModels.size());
if (actionMode != null) {
actionMode.setTitle(title);
}
DiscoverFragment.this.selectedFeedModels = selectedFeedModels;
}
@Override
public void onSelectionEnd() {
if (onBackPressedCallback.isEnabled()) {
onBackPressedCallback.setEnabled(false);
onBackPressedCallback.remove();
}
if (actionMode != null) {
actionMode.finish();
actionMode = null;
}
}
};
@Override @Override
public void onCreate(@Nullable final Bundle savedInstanceState) { public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
fragmentActivity = (MainActivity) requireActivity(); fragmentActivity = (MainActivity) getActivity();
discoverService = DiscoverService.getInstance(); setHasOptionsMenu(true);
// final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID);
// final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
// final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
// final long userId = CookieUtils.getUserIdFromCookie(cookie);
mediaRepository = MediaRepository.Companion.getInstance();
} }
@Override @Override
public View onCreateView(@NonNull final LayoutInflater inflater, public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
final ViewGroup container, final String cookie = settingsHelper.getString(Constants.COOKIE);
final Bundle savedInstanceState) { isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
if (root != null) { if (root != null) {
shouldRefresh = false; shouldRefresh = false;
return root; return root;
} }
binding = FragmentDiscoverBinding.inflate(inflater, container, false); binding = FragmentDiscoverBinding.inflate(getLayoutInflater(), container, false);
root = binding.getRoot(); root = binding.getRoot();
return root; return root;
} }
@ -82,92 +242,67 @@ public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnR
shouldRefresh = false; shouldRefresh = false;
} }
private void init() { @Override
setupTopics(); public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
fetchTopics(); inflater.inflate(R.menu.saved_viewer_menu, menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
if (item.getItemId() == R.id.layout) {
showPostsLayoutPreferences();
return true;
}
return super.onOptionsItemSelected(item);
} }
@Override @Override
public void onRefresh() { public void onRefresh() {
fetchTopics(); binding.posts.refresh();
} }
public void setupTopics() { private void init() {
topicClusterViewModel = new ViewModelProvider(fragmentActivity).get(TopicClusterViewModel.class); final Bundle arguments = getArguments();
binding.topicsRecyclerView.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(2))); if (arguments == null) return;
final DiscoverTopicsAdapter.OnTopicClickListener otcl = new DiscoverTopicsAdapter.OnTopicClickListener() { final DiscoverFragmentArgs fragmentArgs = DiscoverFragmentArgs.fromBundle(arguments);
public void onTopicClick(final TopicCluster topicCluster, final View cover, final int titleColor, final int backgroundColor) { keyword = fragmentArgs.getKeyword();
try { setupPosts();
final FragmentNavigator.Extras.Builder builder = new FragmentNavigator.Extras.Builder()
.addSharedElement(cover, "cover-" + topicCluster.getId());
final NavDirections action = DiscoverFragmentDirections.actionToTopicPosts(topicCluster, titleColor, backgroundColor);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action, builder.build());
} catch (Exception e) {
Log.e(TAG, "onTopicClick: ", e);
}
}
public void onTopicLongClick(final Media coverMedia) {
final AlertDialog alertDialog = new AlertDialog.Builder(requireContext())
.setCancelable(false)
.setView(R.layout.dialog_opening_post)
.create();
alertDialog.show();
final String pk = coverMedia.getPk();
if (pk == null) return;
mediaRepository.fetch(
Long.parseLong(pk),
CoroutineUtilsKt.getContinuation((media, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
alertDialog.dismiss();
try {
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
} catch (Throwable ignored) {}
return;
}
try {
final NavDirections action = DiscoverFragmentDirections.actionToPost(media, 0);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action);
alertDialog.dismiss();
} catch (Exception e) {
Log.e(TAG, "onTopicLongClick: ", e);
}
}), Dispatchers.getIO())
);
}
};
final DiscoverTopicsAdapter adapter = new DiscoverTopicsAdapter(otcl);
binding.topicsRecyclerView.setAdapter(adapter);
topicClusterViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
} }
private void fetchTopics() { private void setupPosts() {
binding.posts.setViewModelStoreOwner(this)
.setLifeCycleOwner(this)
.setPostFetchService(new DiscoverPostFetchService(new DiscoverService.TopicalExploreRequest()))
.setLayoutPreferences(layoutPreferences)
.addFetchStatusChangeListener(fetching -> updateSwipeRefreshState())
.setFeedItemCallback(feedItemCallback)
.setSelectionModeCallback(selectionModeCallback)
.init();
binding.swipeRefreshLayout.setRefreshing(true); binding.swipeRefreshLayout.setRefreshing(true);
discoverService.topicalExplore(new DiscoverService.TopicalExploreRequest(), new ServiceCallback<TopicalExploreFeedResponse>() {
@Override
public void onSuccess(final TopicalExploreFeedResponse result) {
if (result == null) return;
final List<TopicCluster> clusters = result.getClusters();
if (clusters == null || result.getItems() == null) return;
binding.swipeRefreshLayout.setRefreshing(false);
if (clusters.size() == 1 && result.getItems().size() > 0) {
final TopicCluster cluster = clusters.get(0);
if (cluster.getCoverMedia() == null) {
cluster.setCoverMedia(result.getItems().get(0).getMedia());
}
topicClusterViewModel.getList().postValue(Collections.singletonList(cluster));
return;
}
if (clusters.size() > 1 || result.getItems().size() == 0) {
topicClusterViewModel.getList().postValue(clusters);
}
}
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "onFailure", t);
binding.swipeRefreshLayout.setRefreshing(false);
}
});
} }
}
private void updateSwipeRefreshState() {
AppExecutors.INSTANCE.getMainThread().execute(() ->
binding.swipeRefreshLayout.setRefreshing(binding.posts.isFetching())
);
}
private void navigateToProfile(final String username) {
try {
final NavDirections action = DiscoverFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {
final PostsLayoutPreferencesDialogFragment fragment = new PostsLayoutPreferencesDialogFragment(
Constants.PREF_TOPIC_POSTS_LAYOUT,
preferences -> {
layoutPreferences = preferences;
new Handler().postDelayed(() -> binding.posts.setLayoutPreferences(preferences), 200);
});
fragment.show(getChildFragmentManager(), "posts_layout_preferences");
}
}

View File

@ -1,27 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorSurface"> app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".fragments.DiscoverFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout <awais.instagrabber.customviews.PostsRecyclerView
android:id="@+id/swipe_refresh_layout" android:id="@+id/posts"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false" android:clipToPadding="false" />
app:layout_behavior="@string/appbar_scrolling_view_behavior"> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/topics_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="?actionBarSize"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:itemCount="10"
tools:listitem="@layout/item_discover_topic" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -11,9 +11,27 @@
android:label="@string/title_discover" android:label="@string/title_discover"
tools:layout="@layout/fragment_discover"> tools:layout="@layout/fragment_discover">
<argument
android:name="keyword"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
<action <action
android:id="@+id/action_to_topic_posts" android:id="@+id/action_to_comments"
app:destination="@id/topicPostsFragment" /> app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action <action
android:id="@+id/action_to_post" android:id="@+id/action_to_post"
@ -346,44 +364,6 @@
app:destination="@id/profile_non_top" /> app:destination="@id/profile_non_top" />
</dialog> </dialog>
<fragment
android:id="@+id/topicPostsFragment"
android:name="awais.instagrabber.fragments.TopicPostsFragment"
tools:layout="@layout/fragment_topic_posts">
<argument
android:name="topicCluster"
app:argType="awais.instagrabber.repositories.responses.discover.TopicCluster" />
<argument
android:name="titleColor"
app:argType="integer" />
<argument
android:name="backgroundColor"
app:argType="integer" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
</fragment>
<!-- Copy of notification viewer fragment tag --> <!-- Copy of notification viewer fragment tag -->
<!-- Required to get back arrow in action bar --> <!-- Required to get back arrow in action bar -->
<!-- See https://issuetracker.google.com/issues/192395936 --> <!-- See https://issuetracker.google.com/issues/192395936 -->