story archive, so half of #460
This commit is contained in:
parent
6e4fa9fdbf
commit
8ebe8dd0f9
@ -15,7 +15,6 @@ import java.util.List;
|
||||
import awais.instagrabber.adapters.viewholder.StoryListViewHolder;
|
||||
import awais.instagrabber.databinding.ItemNotificationBinding;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, StoryListViewHolder> {
|
||||
@ -49,48 +48,11 @@ public final class FeedStoriesListAdapter extends ListAdapter<FeedStoryModel, St
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final StoryListViewHolder holder, final int position) {
|
||||
final FeedStoryModel model = getItem(position);
|
||||
holder.bind(model, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitList(@Nullable final List<FeedStoryModel> list, @Nullable final Runnable commitCallback) {
|
||||
if (list == null) {
|
||||
super.submitList(null, commitCallback);
|
||||
return;
|
||||
}
|
||||
super.submitList(sort(list), commitCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitList(@Nullable final List<FeedStoryModel> list) {
|
||||
if (list == null) {
|
||||
super.submitList(null);
|
||||
return;
|
||||
}
|
||||
super.submitList(sort(list));
|
||||
}
|
||||
|
||||
private List<FeedStoryModel> sort(final List<FeedStoryModel> list) {
|
||||
final List<FeedStoryModel> listCopy = new ArrayList<>(list);
|
||||
Collections.sort(listCopy, (o1, o2) -> {
|
||||
int result;
|
||||
switch (Utils.settingsHelper.getString(Constants.STORY_SORT)) {
|
||||
case "1":
|
||||
result = o1.getTimestamp() > o2.getTimestamp() ? -1 : (o1.getTimestamp() == o2.getTimestamp() ? 0 : 1);
|
||||
break;
|
||||
case "2":
|
||||
result = o1.getTimestamp() > o2.getTimestamp() ? 1 : (o1.getTimestamp() == o2.getTimestamp() ? 0 : -1);
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return listCopy;
|
||||
holder.bind(model, position, listener);
|
||||
}
|
||||
|
||||
public interface OnFeedStoryClickListener {
|
||||
void onFeedStoryClick(final FeedStoryModel model);
|
||||
void onFeedStoryClick(final FeedStoryModel model, final int position);
|
||||
|
||||
void onProfileClick(final String username);
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ public final class HighlightStoriesListAdapter extends ListAdapter<HighlightMode
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final StoryListViewHolder holder, final int position) {
|
||||
final HighlightModel model = getItem(position);
|
||||
holder.bind(model, listener);
|
||||
holder.bind(model, position, listener);
|
||||
}
|
||||
|
||||
public interface OnHighlightStoryClickListener {
|
||||
void onHighlightClick(HighlightModel model);
|
||||
void onHighlightClick(final HighlightModel model, final int position);
|
||||
|
||||
void onProfileClick(String username);
|
||||
void onProfileClick(final String username);
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,14 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
||||
}
|
||||
|
||||
public void bind(final FeedStoryModel model,
|
||||
final int position,
|
||||
final OnFeedStoryClickListener notificationClickListener) {
|
||||
if (model == null) return;
|
||||
binding.tvComment.setVisibility(View.GONE);
|
||||
|
||||
final int storiesCount = model.getMediaCount();
|
||||
binding.tvComment.setVisibility(View.VISIBLE);
|
||||
binding.tvComment.setText(itemView.getResources().getQuantityString(R.plurals.stories_count, storiesCount, storiesCount));
|
||||
|
||||
binding.tvSubComment.setVisibility(View.GONE);
|
||||
|
||||
binding.tvDate.setText(model.getDateTime());
|
||||
@ -36,22 +41,27 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
||||
});
|
||||
|
||||
binding.ivPreviewPic.setVisibility(View.VISIBLE);
|
||||
binding.ivPreviewPic.setImageURI(model.getFirstStoryModel().getThumbnail());
|
||||
binding.ivPreviewPic.setOnClickListener(v -> {
|
||||
if (notificationClickListener == null) return;
|
||||
notificationClickListener.onFeedStoryClick(model);
|
||||
});
|
||||
if (model.getFirstStoryModel() != null) {
|
||||
binding.ivPreviewPic.setVisibility(View.VISIBLE);
|
||||
binding.ivPreviewPic.setImageURI(model.getFirstStoryModel().getThumbnail());
|
||||
}
|
||||
else binding.ivPreviewPic.setVisibility(View.INVISIBLE);
|
||||
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (notificationClickListener == null) return;
|
||||
notificationClickListener.onFeedStoryClick(model);
|
||||
notificationClickListener.onFeedStoryClick(model, position);
|
||||
});
|
||||
}
|
||||
|
||||
public void bind(final HighlightModel model,
|
||||
final int position,
|
||||
final OnHighlightStoryClickListener notificationClickListener) {
|
||||
if (model == null) return;
|
||||
binding.tvComment.setVisibility(View.GONE);
|
||||
|
||||
final int storiesCount = model.getMediaCount();
|
||||
binding.tvComment.setVisibility(View.VISIBLE);
|
||||
binding.tvComment.setText(itemView.getResources().getQuantityString(R.plurals.stories_count, storiesCount, storiesCount));
|
||||
|
||||
binding.tvSubComment.setVisibility(View.GONE);
|
||||
|
||||
binding.tvUsername.setText(model.getDateTime());
|
||||
@ -63,7 +73,7 @@ public final class StoryListViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (notificationClickListener == null) return;
|
||||
notificationClickListener.onHighlightClick(model);
|
||||
notificationClickListener.onHighlightClick(model, position);
|
||||
});
|
||||
}
|
||||
}
|
@ -545,7 +545,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
if (!hasStories) return;
|
||||
// show stories
|
||||
final NavDirections action = HashTagFragmentDirections
|
||||
.actionHashtagFragmentToStoryViewerFragment(-1, null, true, false, hashtagModel.getName(), hashtagModel.getName());
|
||||
.actionHashtagFragmentToStoryViewerFragment(-1, null, true, false, hashtagModel.getName(), hashtagModel.getName(), false);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
});
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme
|
||||
if (isComment && !isLoggedIn) {
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (!TextUtils.isEmpty(endCursor))
|
||||
graphQLService.fetchCommentLikers(postId, null, acb);
|
||||
graphQLService.fetchCommentLikers(postId, endCursor, acb);
|
||||
endCursor = null;
|
||||
});
|
||||
binding.rvLikes.addOnScrollListener(lazyLoader);
|
||||
|
@ -523,7 +523,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
|
||||
if (hasStories) {
|
||||
// show stories
|
||||
final NavDirections action = LocationFragmentDirections
|
||||
.actionLocationFragmentToStoryViewerFragment(-1, null, false, true, locationId, locationModel.getName());
|
||||
.actionLocationFragmentToStoryViewerFragment(-1, null, false, true, locationId, locationModel.getName(), false);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
}
|
||||
});
|
||||
|
@ -2,12 +2,16 @@ package awais.instagrabber.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
@ -15,34 +19,47 @@ import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.FeedStoriesListAdapter;
|
||||
import awais.instagrabber.adapters.FeedStoriesListAdapter.OnFeedStoryClickListener;
|
||||
import awais.instagrabber.adapters.HighlightStoriesListAdapter;
|
||||
import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryClickListener;
|
||||
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
|
||||
import awais.instagrabber.databinding.FragmentStoryListViewerBinding;
|
||||
import awais.instagrabber.fragments.main.FeedFragment;
|
||||
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.viewmodels.StoriesViewModel;
|
||||
import awais.instagrabber.models.HighlightModel;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.viewmodels.FeedStoriesViewModel;
|
||||
import awais.instagrabber.viewmodels.ArchivesViewModel;
|
||||
import awais.instagrabber.webservices.ServiceCallback;
|
||||
import awais.instagrabber.webservices.StoriesService;
|
||||
|
||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||
import awais.instagrabber.webservices.StoriesService.ArchiveFetchResponse;
|
||||
|
||||
public final class StoryListViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "StoryListViewerFragment";
|
||||
|
||||
private AppCompatActivity fragmentActivity;
|
||||
private FragmentStoryListViewerBinding binding;
|
||||
private SwipeRefreshLayout root;
|
||||
private boolean shouldRefresh = true;
|
||||
private StoriesViewModel storiesViewModel;
|
||||
private FeedStoriesViewModel feedStoriesViewModel;
|
||||
private ArchivesViewModel archivesViewModel;
|
||||
private StoriesService storiesService;
|
||||
private Context context;
|
||||
private String type;
|
||||
private String type, endCursor = null;
|
||||
private RecyclerLazyLoader lazyLoader;
|
||||
|
||||
private final OnFeedStoryClickListener clickListener = new OnFeedStoryClickListener() {
|
||||
@Override
|
||||
public void onFeedStoryClick(final FeedStoryModel model) {
|
||||
public void onFeedStoryClick(final FeedStoryModel model, final int position) {
|
||||
if (model == null) return;
|
||||
// final NavDirections action = StoryListNavGraphDirections.actionStoryListFragmentToStoryViewerFragment(position, null, false, false, null, null);
|
||||
// NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
|
||||
final NavDirections action = StoryListViewerFragmentDirections.actionStoryListFragmentToStoryViewerFragment(position, null, false, false, null, null, false);
|
||||
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,9 +68,47 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
||||
}
|
||||
};
|
||||
|
||||
private final OnHighlightStoryClickListener archiveClickListener = new OnHighlightStoryClickListener() {
|
||||
@Override
|
||||
public void onHighlightClick(final HighlightModel model, final int position) {
|
||||
if (model == null) return;
|
||||
final NavDirections action = StoryListViewerFragmentDirections.actionStoryListFragmentToStoryViewerFragment(
|
||||
position, getString(R.string.action_archive), false, false, null, null, true);
|
||||
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProfileClick(final String username) {
|
||||
openProfile(username);
|
||||
}
|
||||
};
|
||||
|
||||
private final ServiceCallback<ArchiveFetchResponse> cb = new ServiceCallback<ArchiveFetchResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final ArchiveFetchResponse result) {
|
||||
endCursor = result.getNextCursor();
|
||||
final List<HighlightModel> models = archivesViewModel.getList().getValue();
|
||||
final List<HighlightModel> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
|
||||
modelsCopy.addAll(result.getResult());
|
||||
archivesViewModel.getList().postValue(modelsCopy);
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
Log.e(TAG, "Error", t);
|
||||
try {
|
||||
final Context context = getContext();
|
||||
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
catch (Exception e) {}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
fragmentActivity = (AppCompatActivity) requireActivity();
|
||||
context = getContext();
|
||||
if (context == null) return;
|
||||
storiesService = StoriesService.getInstance();
|
||||
@ -78,26 +133,54 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
|
||||
shouldRefresh = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (archivesViewModel != null) archivesViewModel.getList().postValue(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
final Context context = getContext();
|
||||
if (getArguments() == null) return;
|
||||
final StoryListViewerFragmentArgs fragmentArgs = StoryListViewerFragmentArgs.fromBundle(getArguments());
|
||||
type = fragmentArgs.getType();
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(this);
|
||||
storiesViewModel = new ViewModelProvider(this).get(StoriesViewModel.class);
|
||||
// final NotificationsAdapter adapter = new NotificationsAdapter(clickListener, mentionClickListener);
|
||||
binding.rvStories.setLayoutManager(new LinearLayoutManager(context));
|
||||
// binding.rvStories.setAdapter(adapter);
|
||||
// storiesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (type == "feed") {
|
||||
if (actionBar != null) actionBar.setTitle(R.string.feed_stories);
|
||||
feedStoriesViewModel = new ViewModelProvider(this).get(FeedStoriesViewModel.class);
|
||||
final FeedStoriesListAdapter adapter = new FeedStoriesListAdapter(clickListener);
|
||||
binding.rvStories.setLayoutManager(layoutManager);
|
||||
binding.rvStories.setAdapter(adapter);
|
||||
feedStoriesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||
}
|
||||
else {
|
||||
if (actionBar != null) actionBar.setTitle(R.string.action_archive);
|
||||
lazyLoader = new RecyclerLazyLoader(layoutManager, (page, totalItemsCount) -> {
|
||||
if (!TextUtils.isEmpty(endCursor)) onRefresh();
|
||||
endCursor = null;
|
||||
});
|
||||
binding.rvStories.addOnScrollListener(lazyLoader);
|
||||
archivesViewModel = new ViewModelProvider(fragmentActivity).get(ArchivesViewModel.class);
|
||||
final HighlightStoriesListAdapter adapter = new HighlightStoriesListAdapter(archiveClickListener);
|
||||
binding.rvStories.setLayoutManager(layoutManager);
|
||||
binding.rvStories.setAdapter(adapter);
|
||||
archivesViewModel.getList().observe(getViewLifecycleOwner(), adapter::submitList);
|
||||
}
|
||||
onRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
|
||||
if (type == "feed") {
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
// storiesViewModel.getList().postValue();
|
||||
feedStoriesViewModel.getList().postValue(FeedFragment.feedStories);
|
||||
}
|
||||
else if (type == "archive") {
|
||||
storiesService.fetchArchive(endCursor, cb);
|
||||
}
|
||||
}
|
||||
|
||||
private void openProfile(final String username) {
|
||||
|
@ -91,6 +91,7 @@ import awais.instagrabber.utils.CookieUtils;
|
||||
import awais.instagrabber.utils.DownloadUtils;
|
||||
import awais.instagrabber.utils.TextUtils;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
import awais.instagrabber.viewmodels.ArchivesViewModel;
|
||||
import awais.instagrabber.viewmodels.FeedStoriesViewModel;
|
||||
import awais.instagrabber.viewmodels.HighlightsViewModel;
|
||||
import awais.instagrabber.viewmodels.StoriesViewModel;
|
||||
@ -138,7 +139,7 @@ public class StoryViewerFragment extends Fragment {
|
||||
private boolean shouldRefresh = true;
|
||||
private StoryViewerFragmentArgs fragmentArgs;
|
||||
private ViewModel viewModel;
|
||||
private boolean isHighlight;
|
||||
private boolean isHighlight, isArchive;
|
||||
|
||||
private final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
|
||||
@ -255,9 +256,12 @@ public class StoryViewerFragment extends Fragment {
|
||||
currentFeedStoryIndex = fragmentArgs.getFeedStoryIndex();
|
||||
highlight = fragmentArgs.getHighlight();
|
||||
isHighlight = !TextUtils.isEmpty(highlight);
|
||||
isArchive = fragmentArgs.getIsArchive();
|
||||
if (currentFeedStoryIndex >= 0) {
|
||||
viewModel = isHighlight
|
||||
? new ViewModelProvider(fragmentActivity).get(HighlightsViewModel.class)
|
||||
? isArchive
|
||||
? new ViewModelProvider(fragmentActivity).get(ArchivesViewModel.class)
|
||||
: new ViewModelProvider(fragmentActivity).get(HighlightsViewModel.class)
|
||||
: new ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel.class);
|
||||
}
|
||||
// feedStoryModels = feedStoriesViewModel.getList().getValue();
|
||||
@ -287,7 +291,11 @@ public class StoryViewerFragment extends Fragment {
|
||||
final boolean hasFeedStories;
|
||||
List<?> models = null;
|
||||
if (currentFeedStoryIndex >= 0) {
|
||||
if (isHighlight) {
|
||||
if (isArchive) {
|
||||
final ArchivesViewModel archivesViewModel = (ArchivesViewModel) viewModel;
|
||||
models = archivesViewModel.getList().getValue();
|
||||
}
|
||||
else if (isHighlight) {
|
||||
final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
|
||||
models = highlightsViewModel.getList().getValue();
|
||||
// final HighlightModel model = models.get(currentFeedStoryIndex);
|
||||
@ -633,7 +641,18 @@ public class StoryViewerFragment extends Fragment {
|
||||
releasePlayer();
|
||||
String currentStoryMediaId = null;
|
||||
if (currentFeedStoryIndex >= 0) {
|
||||
if (isHighlight) {
|
||||
if (isArchive) {
|
||||
final ArchivesViewModel archivesViewModel = (ArchivesViewModel) viewModel;
|
||||
final List<HighlightModel> models = archivesViewModel.getList().getValue();
|
||||
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size()) {
|
||||
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
final HighlightModel model = models.get(currentFeedStoryIndex);
|
||||
currentStoryMediaId = model.getId();
|
||||
currentStoryUsername = model.getTitle();
|
||||
}
|
||||
else if (isHighlight) {
|
||||
final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
|
||||
final List<HighlightModel> models = highlightsViewModel.getList().getValue();
|
||||
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size()) {
|
||||
@ -658,7 +677,13 @@ public class StoryViewerFragment extends Fragment {
|
||||
isHashtag = fragmentArgs.getIsHashtag();
|
||||
isLoc = fragmentArgs.getIsLoc();
|
||||
final boolean hasUsername = !TextUtils.isEmpty(currentStoryUsername);
|
||||
if (hasUsername) {
|
||||
if (isHighlight) {
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(highlight);
|
||||
}
|
||||
}
|
||||
else if (hasUsername) {
|
||||
currentStoryUsername = currentStoryUsername.replace("@", "");
|
||||
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
|
@ -78,6 +78,8 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
||||
private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_POSTS_LAYOUT);
|
||||
private RecyclerView storiesRecyclerView;
|
||||
|
||||
public static List<FeedStoryModel> feedStories;
|
||||
|
||||
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
|
||||
@Override
|
||||
public void onPostClick(final FeedModel feedModel, final View profilePicView, final View mainPostImage) {
|
||||
@ -362,7 +364,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
||||
new FeedStoriesAdapter.OnFeedStoryClickListener() {
|
||||
@Override
|
||||
public void onFeedStoryClick(FeedStoryModel model, int position) {
|
||||
final NavDirections action = FeedFragmentDirections.actionFeedFragmentToStoryViewerFragment(position, null, false, false, null, null);
|
||||
final NavDirections action = FeedFragmentDirections.actionFeedFragmentToStoryViewerFragment(position, null, false, false, null, null, false);
|
||||
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
|
||||
}
|
||||
|
||||
@ -398,6 +400,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
|
||||
@Override
|
||||
public void onSuccess(final List<FeedStoryModel> result) {
|
||||
feedStoriesViewModel.getList().postValue(result);
|
||||
feedStories = result;
|
||||
storiesFetching = false;
|
||||
updateSwipeRefreshState();
|
||||
}
|
||||
|
@ -1008,7 +1008,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
if (which == 1) {
|
||||
// show stories
|
||||
final NavDirections action = ProfileFragmentDirections
|
||||
.actionProfileFragmentToStoryViewerFragment(-1, null, false, false, profileModel.getId(), username);
|
||||
.actionProfileFragmentToStoryViewerFragment(-1, null, false, false, profileModel.getId(), username, false);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
return;
|
||||
}
|
||||
@ -1069,7 +1069,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
highlightsViewModel = new ViewModelProvider(fragmentActivity).get(HighlightsViewModel.class);
|
||||
highlightsAdapter = new HighlightsAdapter((model, position) -> {
|
||||
final NavDirections action = ProfileFragmentDirections
|
||||
.actionProfileFragmentToStoryViewerFragment(position, model.getTitle(), false, false, null, null);
|
||||
.actionProfileFragmentToStoryViewerFragment(position, model.getTitle(), false, false, null, null, false);
|
||||
NavHostFragment.findNavController(this).navigate(action);
|
||||
});
|
||||
final Context context = getContext();
|
||||
|
@ -15,14 +15,16 @@ public final class FeedStoryModel implements Serializable {
|
||||
private final StoryModel firstStoryModel;
|
||||
private Boolean fullyRead;
|
||||
private final long timestamp;
|
||||
private final int mediaCount;
|
||||
|
||||
public FeedStoryModel(final String storyMediaId, final ProfileModel profileModel,
|
||||
final boolean fullyRead, final long timestamp, final StoryModel firstStoryModel) {
|
||||
public FeedStoryModel(final String storyMediaId, final ProfileModel profileModel, final boolean fullyRead,
|
||||
final long timestamp, final StoryModel firstStoryModel, final int mediaCount) {
|
||||
this.storyMediaId = storyMediaId;
|
||||
this.profileModel = profileModel;
|
||||
this.fullyRead = fullyRead;
|
||||
this.timestamp = timestamp;
|
||||
this.firstStoryModel = firstStoryModel;
|
||||
this.mediaCount = mediaCount;
|
||||
}
|
||||
|
||||
public String getStoryMediaId() {
|
||||
@ -38,6 +40,10 @@ public final class FeedStoryModel implements Serializable {
|
||||
return Utils.datetimeParser.format(new Date(timestamp * 1000L));
|
||||
}
|
||||
|
||||
public int getMediaCount() {
|
||||
return mediaCount;
|
||||
}
|
||||
|
||||
public ProfileModel getProfileModel() {
|
||||
return profileModel;
|
||||
}
|
||||
|
@ -11,15 +11,18 @@ public final class HighlightModel {
|
||||
private final String id;
|
||||
private final String thumbnailUrl;
|
||||
private final long timestamp;
|
||||
private final int mediaCount;
|
||||
|
||||
public HighlightModel(final String title,
|
||||
final String id,
|
||||
final String thumbnailUrl,
|
||||
final long timestamp) {
|
||||
final long timestamp,
|
||||
final int mediaCount) {
|
||||
this.title = title;
|
||||
this.id = id;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.timestamp = timestamp;
|
||||
this.mediaCount = mediaCount;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
@ -42,4 +45,8 @@ public final class HighlightModel {
|
||||
public String getDateTime() {
|
||||
return Utils.datetimeParser.format(new Date(timestamp * 1000L));
|
||||
}
|
||||
|
||||
public int getMediaCount() {
|
||||
return mediaCount;
|
||||
}
|
||||
}
|
@ -11,7 +11,8 @@ import awais.instagrabber.models.stickers.SwipeUpModel;
|
||||
|
||||
public final class StoryModel implements Serializable {
|
||||
private final String storyMediaId;
|
||||
private final String storyUrl, thumbnail;
|
||||
private final String storyUrl;
|
||||
private String thumbnail;
|
||||
private final String username;
|
||||
private final String userId;
|
||||
private final MediaItemType itemType;
|
||||
@ -96,6 +97,10 @@ public final class StoryModel implements Serializable {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setThumbnail(final String thumbnail) {
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
|
||||
public void setVideoUrl(final String videoUrl) {
|
||||
this.videoUrl = videoUrl;
|
||||
}
|
||||
|
@ -18,10 +18,8 @@ public interface StoriesRepository {
|
||||
Call<String> fetch(@Path("mediaId") final String mediaId);
|
||||
// this one is the same as MediaRepository.fetch BUT you need to make sure it's a story
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/feed/reels_tray/")
|
||||
Call<String> getFeedStories(@Header("User-Agent") String userAgent,
|
||||
@FieldMap Map<String, String> form);
|
||||
@GET("/api/v1/feed/reels_tray/")
|
||||
Call<String> getFeedStories();
|
||||
|
||||
@GET("/api/v1/highlights/{uid}/highlights_tray/")
|
||||
Call<String> fetchHighlights(@Path("uid") final String uid);
|
||||
|
@ -889,9 +889,7 @@ public final class ResponseBodyUtils {
|
||||
final boolean isVideo = data.has("video_duration");
|
||||
final StoryModel model = new StoryModel(data.getString("id"),
|
||||
data.getJSONObject("image_versions2").getJSONArray("candidates").getJSONObject(0)
|
||||
.getString("url"),
|
||||
data.getJSONObject("image_versions2").getJSONArray("candidates").getJSONObject(1)
|
||||
.getString("url"),
|
||||
.getString("url"), null,
|
||||
isVideo ? MediaItemType.MEDIA_TYPE_VIDEO : MediaItemType.MEDIA_TYPE_IMAGE,
|
||||
data.optLong("taken_at", 0),
|
||||
(isLoc || isHashtag)
|
||||
@ -900,6 +898,11 @@ public final class ResponseBodyUtils {
|
||||
data.getJSONObject("user").getString("pk"),
|
||||
data.optBoolean("can_reply"));
|
||||
|
||||
if (data.getJSONObject("image_versions2").getJSONArray("candidates").length() > 1) {
|
||||
model.setThumbnail(data.getJSONObject("image_versions2").getJSONArray("candidates").getJSONObject(1)
|
||||
.getString("url"));
|
||||
}
|
||||
|
||||
final JSONArray videoResources = data.optJSONArray("video_versions");
|
||||
if (isVideo && videoResources != null)
|
||||
model.setVideoUrl(ResponseBodyUtils.getHighQualityPost(videoResources, true, true, false));
|
||||
|
@ -0,0 +1,19 @@
|
||||
package awais.instagrabber.viewmodels;
|
||||
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.models.HighlightModel;
|
||||
|
||||
public class ArchivesViewModel extends ViewModel {
|
||||
private MutableLiveData<List<HighlightModel>> list;
|
||||
|
||||
public MutableLiveData<List<HighlightModel>> getList() {
|
||||
if (list == null) {
|
||||
list = new MutableLiveData<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -84,13 +85,7 @@ public class StoriesService extends BaseService {
|
||||
}
|
||||
|
||||
public void getFeedStories(final String csrfToken, final ServiceCallback<List<FeedStoryModel>> callback) {
|
||||
final Map<String, Object> form = new HashMap<>(4);
|
||||
form.put("reason", "cold_start");
|
||||
form.put("_csrftoken", csrfToken);
|
||||
form.put("_uuid", UUID.randomUUID().toString());
|
||||
form.put("supported_capabilities_new", Constants.SUPPORTED_CAPABILITIES);
|
||||
final Map<String, String> signedForm = Utils.sign(form);
|
||||
final Call<String> response = repository.getFeedStories(Constants.I_USER_AGENT, signedForm);
|
||||
final Call<String> response = repository.getFeedStories();
|
||||
response.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
@ -124,12 +119,17 @@ public class StoriesService extends BaseService {
|
||||
null, 0, 0, 0, false, false, false, false, false);
|
||||
final String id = node.getString("id");
|
||||
final long timestamp = node.getLong("latest_reel_media");
|
||||
final int mediaCount = node.getInt("media_count");
|
||||
final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp;
|
||||
final JSONObject itemJson = node.getJSONArray("items").getJSONObject(0);
|
||||
final StoryModel firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, false, null);
|
||||
feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead, timestamp, firstStoryModel));
|
||||
final JSONObject itemJson = node.has("items") ? node.getJSONArray("items").getJSONObject(0) : null;
|
||||
StoryModel firstStoryModel = null;
|
||||
if (itemJson != null) {
|
||||
firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, false, null);
|
||||
}
|
||||
else Log.d("austin_debug", "node: "+node);
|
||||
feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead, timestamp, firstStoryModel, mediaCount));
|
||||
}
|
||||
callback.onSuccess(feedStoryModels);
|
||||
callback.onSuccess(sort(feedStoryModels));
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error parsing json", e);
|
||||
}
|
||||
@ -163,7 +163,8 @@ public class StoriesService extends BaseService {
|
||||
highlightNode.getJSONObject("cover_media")
|
||||
.getJSONObject("cropped_image_version")
|
||||
.getString("url"),
|
||||
highlightNode.getLong("latest_reel_media")
|
||||
highlightNode.getLong("latest_reel_media"),
|
||||
highlightNode.getInt("media_count")
|
||||
));
|
||||
}
|
||||
callback.onSuccess(highlightModels);
|
||||
@ -217,7 +218,8 @@ public class StoriesService extends BaseService {
|
||||
null,
|
||||
highlightNode.getString(Constants.EXTRAS_ID),
|
||||
highlightNode.getJSONObject("cover_image_version").getString("url"),
|
||||
highlightNode.getLong("timestamp")
|
||||
highlightNode.getLong("timestamp"),
|
||||
highlightNode.getInt("media_count")
|
||||
));
|
||||
}
|
||||
callback.onSuccess(new ArchiveFetchResponse(highlightModels,
|
||||
@ -393,6 +395,25 @@ public class StoriesService extends BaseService {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private List<FeedStoryModel> sort(final List<FeedStoryModel> list) {
|
||||
final List<FeedStoryModel> listCopy = new ArrayList<>(list);
|
||||
Collections.sort(listCopy, (o1, o2) -> {
|
||||
int result;
|
||||
switch (Utils.settingsHelper.getString(Constants.STORY_SORT)) {
|
||||
case "1":
|
||||
result = o1.getTimestamp() > o2.getTimestamp() ? -1 : (o1.getTimestamp() == o2.getTimestamp() ? 0 : 1);
|
||||
break;
|
||||
case "2":
|
||||
result = o1.getTimestamp() > o2.getTimestamp() ? 1 : (o1.getTimestamp() == o2.getTimestamp() ? 0 : -1);
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return listCopy;
|
||||
}
|
||||
|
||||
public class ArchiveFetchResponse {
|
||||
private final List<HighlightModel> archives;
|
||||
private final boolean hasNextPage;
|
||||
@ -404,7 +425,7 @@ public class StoriesService extends BaseService {
|
||||
this.nextCursor = nextCursor;
|
||||
}
|
||||
|
||||
public List<HighlightModel> getArchives() {
|
||||
public List<HighlightModel> getResult() {
|
||||
return archives;
|
||||
}
|
||||
|
||||
@ -416,5 +437,4 @@ public class StoriesService extends BaseService {
|
||||
return nextCursor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -125,5 +125,9 @@
|
||||
android:name="username"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="isArchive"
|
||||
app:argType="boolean"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
</navigation>
|
@ -97,6 +97,10 @@
|
||||
android:name="username"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="isArchive"
|
||||
app:argType="boolean"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
<action
|
||||
android:id="@+id/action_global_hashTagFragment"
|
||||
|
@ -105,5 +105,9 @@
|
||||
android:name="username"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="isArchive"
|
||||
app:argType="boolean"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
</navigation>
|
@ -174,6 +174,10 @@
|
||||
android:name="username"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="isArchive"
|
||||
app:argType="boolean"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/directMessagesThreadFragment"
|
||||
|
@ -64,5 +64,9 @@
|
||||
android:name="username"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="isArchive"
|
||||
app:argType="boolean"
|
||||
app:nullable="false" />
|
||||
</fragment>
|
||||
</navigation>
|
@ -347,5 +347,9 @@
|
||||
<item quantity="one">%d comment</item>
|
||||
<item quantity="other">%d comments</item>
|
||||
</plurals>
|
||||
<plurals name="stories_count">
|
||||
<item quantity="one">%s story</item>
|
||||
<item quantity="other">%s stories</item>
|
||||
</plurals>
|
||||
<string name="download_permission">Storage permission not granted!</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user