story archive, so half of #460

This commit is contained in:
Austin Huang 2020-12-29 17:33:44 -05:00
parent 6e4fa9fdbf
commit 8ebe8dd0f9
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
23 changed files with 270 additions and 105 deletions

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
});
}
}

View File

@ -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);
});
}

View File

@ -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);

View File

@ -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);
}
});

View File

@ -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) {

View File

@ -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) {

View File

@ -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();
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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>