diff --git a/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java b/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java index 05966afd..821a1c7b 100755 --- a/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/FeedStoriesAdapter.java @@ -9,20 +9,20 @@ import androidx.recyclerview.widget.ListAdapter; import awais.instagrabber.adapters.viewholder.FeedStoryViewHolder; import awais.instagrabber.databinding.ItemHighlightBinding; -import awais.instagrabber.models.FeedStoryModel; +import awais.instagrabber.repositories.responses.stories.Story; -public final class FeedStoriesAdapter extends ListAdapter { +public final class FeedStoriesAdapter extends ListAdapter { private final OnFeedStoryClickListener listener; - private static final DiffUtil.ItemCallback diffCallback = new DiffUtil.ItemCallback() { + private static final DiffUtil.ItemCallback diffCallback = new DiffUtil.ItemCallback() { @Override - public boolean areItemsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) { - return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId()); + public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) { + return oldItem.getId().equals(newItem.getId()); } @Override - public boolean areContentsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) { - return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId()) && oldItem.isFullyRead() == newItem.isFullyRead(); + public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) { + return oldItem.getId().equals(newItem.getId()) && oldItem.getSeen() == newItem.getSeen(); } }; @@ -41,13 +41,13 @@ public final class FeedStoriesAdapter extends ListAdapter implements Filterable { +public final class FeedStoriesListAdapter extends ListAdapter implements Filterable { private final OnFeedStoryClickListener listener; - private List list; + private List list; private final Filter filter = new Filter() { @NonNull @Override protected FilterResults performFiltering(final CharSequence filter) { final String query = TextUtils.isEmpty(filter) ? null : filter.toString().toLowerCase(); - List filteredList = list; + List filteredList = list; if (list != null && query != null) { filteredList = list.stream() - .filter(feedStoryModel -> feedStoryModel.getProfileModel() + .filter(feedStoryModel -> feedStoryModel.getUser() .getUsername() .toLowerCase() .contains(query)) @@ -45,19 +45,19 @@ public final class FeedStoriesListAdapter extends ListAdapter) results.values, true); + submitList((List) results.values, true); } }; - private static final DiffUtil.ItemCallback diffCallback = new DiffUtil.ItemCallback() { + private static final DiffUtil.ItemCallback diffCallback = new DiffUtil.ItemCallback() { @Override - public boolean areItemsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) { - return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId()); + public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) { + return oldItem.getId().equals(newItem.getId()); } @Override - public boolean areContentsTheSame(@NonNull final FeedStoryModel oldItem, @NonNull final FeedStoryModel newItem) { - return oldItem.getStoryMediaId().equals(newItem.getStoryMediaId()) && oldItem.isFullyRead() == newItem.isFullyRead(); + public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) { + return oldItem.getId().equals(newItem.getId()) && oldItem.getSeen() == newItem.getSeen(); } }; @@ -71,7 +71,7 @@ public final class FeedStoriesListAdapter extends ListAdapter list, final boolean isFiltered) { + private void submitList(@Nullable final List list, final boolean isFiltered) { if (!isFiltered) { this.list = list; } @@ -79,7 +79,7 @@ public final class FeedStoriesListAdapter extends ListAdapter list) { + public void submitList(final List list) { submitList(list, false); } @@ -93,12 +93,12 @@ public final class FeedStoriesListAdapter extends ListAdapter { if (notificationClickListener == null) return; - notificationClickListener.onProfileClick(model.getProfileModel().getUsername()); + notificationClickListener.onProfileClick(model.getUser().getUsername()); }); - if (model.getFirstStoryModel() != null) { + if (model.getItems() != null && model.getItems().size() > 0) { binding.ivPreviewPic.setVisibility(View.VISIBLE); - binding.ivPreviewPic.setImageURI(model.getFirstStoryModel().getThumbnail()); + binding.ivPreviewPic.setImageURI(ResponseBodyUtils.getThumbUrl(model.getItems().get(0))); } else binding.ivPreviewPic.setVisibility(View.INVISIBLE); - float alpha = model.isFullyRead() ? 0.5F : 1.0F; + float alpha = model.getSeen() != null && model.getSeen().equals(model.getLatestReelMedia()) + ? 0.5F : 1.0F; binding.ivProfilePic.setAlpha(alpha); binding.ivPreviewPic.setAlpha(alpha); binding.tvUsername.setAlpha(alpha); diff --git a/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java index 8bdfd548..c259b1c4 100644 --- a/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/StoryListViewerFragment.java @@ -38,9 +38,9 @@ import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryC import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; import awais.instagrabber.databinding.FragmentStoryListViewerBinding; import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections; -import awais.instagrabber.models.FeedStoryModel; import awais.instagrabber.models.HighlightModel; import awais.instagrabber.repositories.requests.StoryViewerOptions; +import awais.instagrabber.repositories.responses.stories.Story; import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.CoroutineUtilsKt; import awais.instagrabber.utils.TextUtils; @@ -69,12 +69,12 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr private final OnFeedStoryClickListener clickListener = new OnFeedStoryClickListener() { @Override - public void onFeedStoryClick(final FeedStoryModel model) { + public void onFeedStoryClick(final Story model) { if (model == null) return; - final List feedStoryModels = feedStoriesViewModel.getList().getValue(); + final List feedStoryModels = feedStoriesViewModel.getList().getValue(); if (feedStoryModels == null) return; final int position = Iterables.indexOf(feedStoryModels, feedStoryModel -> feedStoryModel != null - && Objects.equals(feedStoryModel.getStoryMediaId(), model.getStoryMediaId())); + && Objects.equals(feedStoryModel.getId(), model.getId())); final NavDirections action = StoryListViewerFragmentDirections .actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position)); NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action); @@ -236,7 +236,7 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr binding.swipeRefreshLayout.setRefreshing(true); if (type.equals("feed") && firstRefresh) { binding.swipeRefreshLayout.setRefreshing(false); - final List value = feedStoriesViewModel.getList().getValue(); + final List value = feedStoriesViewModel.getList().getValue(); if (value != null) { adapter.submitList(value); } @@ -250,9 +250,9 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr return; } //noinspection unchecked - feedStoriesViewModel.getList().postValue((List) feedStoryModels); + feedStoriesViewModel.getList().postValue((List) feedStoryModels); //noinspection unchecked - adapter.submitList((List) feedStoryModels); + adapter.submitList((List) feedStoryModels); binding.swipeRefreshLayout.setRefreshing(false); }), Dispatchers.getIO()) ); diff --git a/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java b/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java index b24ad0f2..a4acc407 100644 --- a/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/StoryViewerFragment.java @@ -75,7 +75,6 @@ import awais.instagrabber.databinding.FragmentStoryViewerBinding; import awais.instagrabber.fragments.main.ProfileFragmentDirections; import awais.instagrabber.fragments.settings.PreferenceKeys; import awais.instagrabber.interfaces.SwipeEvent; -import awais.instagrabber.models.FeedStoryModel; import awais.instagrabber.models.HighlightModel; import awais.instagrabber.models.StoryModel; import awais.instagrabber.models.enums.MediaItemType; @@ -87,6 +86,8 @@ import awais.instagrabber.models.stickers.SwipeUpModel; import awais.instagrabber.repositories.requests.StoryViewerOptions; import awais.instagrabber.repositories.requests.StoryViewerOptions.Type; import awais.instagrabber.repositories.requests.directmessages.ThreadIdsOrUserIds; +import awais.instagrabber.repositories.responses.stories.Broadcast; +import awais.instagrabber.repositories.responses.stories.Story; import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.CookieUtils; @@ -125,6 +126,7 @@ public class StoryViewerFragment extends Fragment { private StoriesRepository storiesRepository; private MediaRepository mediaRepository; private StoryModel currentStory; + private Broadcast live; private int slidePos; private int lastSlidePos; private String url; @@ -717,7 +719,7 @@ public class StoryViewerFragment extends Fragment { private void resetView() { final Context context = getContext(); if (context == null) return; - StoryModel live = null; + live = null; slidePos = 0; lastSlidePos = 0; if (menuDownload != null) menuDownload.setVisible(false); @@ -747,15 +749,13 @@ public class StoryViewerFragment extends Fragment { } case FEED_STORY_POSITION: { final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel; - final List models = feedStoriesViewModel.getList().getValue(); + final List models = feedStoriesViewModel.getList().getValue(); if (models == null || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) return; - final FeedStoryModel model = models.get(currentFeedStoryIndex); - currentStoryMediaId = model.getStoryMediaId(); - currentStoryUsername = model.getProfileModel().getUsername(); + final Story model = models.get(currentFeedStoryIndex); + currentStoryMediaId = model.getId(); + currentStoryUsername = model.getUser().getUsername(); fetchOptions = StoryViewerOptions.forUser(Long.parseLong(currentStoryMediaId), currentStoryUsername); - if (model.isLive()) { - live = model.getFirstStoryModel(); - } + live = model.getBroadcast(); break; } case STORY_ARCHIVE: { @@ -803,6 +803,11 @@ public class StoryViewerFragment extends Fragment { return; } if (currentStoryMediaId == null) return; + if (live != null) { + currentStory = null; + refreshLive(); + return; + } final ServiceCallback> storyCallback = new ServiceCallback>() { @Override public void onSuccess(final List storyModels) { @@ -829,10 +834,6 @@ public class StoryViewerFragment extends Fragment { Log.e(TAG, "Error", t); } }; - if (live != null) { - storyCallback.onSuccess(Collections.singletonList(live)); - return; - } storiesRepository.getUserStory( fetchOptions, CoroutineUtilsKt.getContinuation((storyModels, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { @@ -864,6 +865,30 @@ public class StoryViewerFragment extends Fragment { } } + private synchronized void refreshLive() { + binding.storiesList.setVisibility(View.INVISIBLE); + binding.viewStoryPost.setVisibility(View.GONE); + binding.spotify.setVisibility(View.GONE); + binding.poll.setVisibility(View.GONE); + binding.answer.setVisibility(View.GONE); + binding.mention.setVisibility(View.GONE); + binding.quiz.setVisibility(View.GONE); + binding.slider.setVisibility(View.GONE); + lastSlidePos = slidePos; + releasePlayer(); + url = live.getDashPlaybackUrl(); + setupLive(); + final ActionBar actionBar = fragmentActivity.getSupportActionBar(); + actionBarSubtitle = TextUtils.epochSecondToString(live.getPublishedTime()); + if (actionBar != null) { + try { + actionBar.setSubtitle(actionBarSubtitle); + } catch (Exception e) { + Log.e(TAG, "refreshLive: ", e); + } + } + } + private synchronized void refreshStory() { if (binding.storiesList.getVisibility() == View.VISIBLE) { final List storyModels = storiesViewModel.getList().getValue(); @@ -886,42 +911,40 @@ public class StoryViewerFragment extends Fragment { url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl(); - if (itemType != MediaItemType.MEDIA_TYPE_LIVE) { - final String shortCode = currentStory.getTappableShortCode(); - binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE); - binding.viewStoryPost.setTag(shortCode); - - final String spotify = currentStory.getSpotify(); - binding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE); - binding.spotify.setTag(spotify); - - poll = currentStory.getPoll(); - binding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE); - binding.poll.setTag(poll); - - question = currentStory.getQuestion(); - binding.answer.setVisibility((question != null) ? View.VISIBLE : View.GONE); - binding.answer.setTag(question); - - mentions = currentStory.getMentions(); - binding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE); - binding.mention.setTag(mentions); - - quiz = currentStory.getQuiz(); - binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE); - binding.quiz.setTag(quiz); - - slider = currentStory.getSlider(); - binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE); - binding.slider.setTag(slider); - - final SwipeUpModel swipeUp = currentStory.getSwipeUp(); - if (swipeUp != null) { - binding.swipeUp.setVisibility(View.VISIBLE); - binding.swipeUp.setText(swipeUp.getText()); - binding.swipeUp.setTag(swipeUp.getUrl()); - } else binding.swipeUp.setVisibility(View.GONE); - } + final String shortCode = currentStory.getTappableShortCode(); + binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE); + binding.viewStoryPost.setTag(shortCode); + + final String spotify = currentStory.getSpotify(); + binding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE); + binding.spotify.setTag(spotify); + + poll = currentStory.getPoll(); + binding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE); + binding.poll.setTag(poll); + + question = currentStory.getQuestion(); + binding.answer.setVisibility((question != null) ? View.VISIBLE : View.GONE); + binding.answer.setTag(question); + + mentions = currentStory.getMentions(); + binding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE); + binding.mention.setTag(mentions); + + quiz = currentStory.getQuiz(); + binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE); + binding.quiz.setTag(quiz); + + slider = currentStory.getSlider(); + binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE); + binding.slider.setTag(slider); + + final SwipeUpModel swipeUp = currentStory.getSwipeUp(); + if (swipeUp != null) { + binding.swipeUp.setVisibility(View.VISIBLE); + binding.swipeUp.setText(swipeUp.getText()); + binding.swipeUp.setTag(swipeUp.getUrl()); + } else binding.swipeUp.setVisibility(View.GONE); releasePlayer(); final Type type = options.getType(); @@ -933,7 +956,6 @@ public class StoryViewerFragment extends Fragment { } } if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo(); - else if (itemType == MediaItemType.MEDIA_TYPE_LIVE) setupLive(); else setupImage(); final ActionBar actionBar = fragmentActivity.getSupportActionBar(); @@ -1205,14 +1227,14 @@ public class StoryViewerFragment extends Fragment { return; } if (settingsHelper.getBoolean(MARK_AS_SEEN) - && oldFeedStory instanceof FeedStoryModel + && oldFeedStory instanceof Story && viewModel instanceof FeedStoriesViewModel) { final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel; - final FeedStoryModel oldFeedStoryModel = (FeedStoryModel) oldFeedStory; - if (!oldFeedStoryModel.isFullyRead()) { - oldFeedStoryModel.setFullyRead(true); - final List models = feedStoriesViewModel.getList().getValue(); - final List modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models); + final Story oldFeedStoryModel = (Story) oldFeedStory; + if (oldFeedStoryModel.getSeen() == null || !oldFeedStoryModel.getSeen().equals(oldFeedStoryModel.getLatestReelMedia())) { + oldFeedStoryModel.setSeen(oldFeedStoryModel.getLatestReelMedia()); + final List models = feedStoriesViewModel.getList().getValue(); + final List modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models); modelsCopy.set(currentFeedStoryIndex, oldFeedStoryModel); feedStoriesViewModel.getList().postValue(models); } diff --git a/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java index 25a354ea..c791823c 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/FeedFragment.java @@ -43,9 +43,9 @@ import awais.instagrabber.customviews.PrimaryActionModeCallback; import awais.instagrabber.databinding.FragmentFeedBinding; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.fragments.PostViewV2Fragment; -import awais.instagrabber.models.FeedStoryModel; import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.repositories.requests.StoryViewerOptions; +import awais.instagrabber.repositories.responses.stories.Story; import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.Constants; @@ -76,7 +76,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre private final FeedStoriesAdapter feedStoriesAdapter = new FeedStoriesAdapter( new FeedStoriesAdapter.OnFeedStoryClickListener() { @Override - public void onFeedStoryClick(FeedStoryModel model, int position) { + public void onFeedStoryClick(Story model, int position) { final NavController navController = NavHostFragment.findNavController(FeedFragment.this); if (isSafeToNavigate(navController)) { final NavDirections action = FeedFragmentDirections @@ -86,8 +86,8 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre } @Override - public void onFeedStoryLongClick(FeedStoryModel model, int position) { - navigateToProfile("@" + model.getProfileModel().getUsername()); + public void onFeedStoryLongClick(Story model, int position) { + navigateToProfile("@" + model.getUser().getUsername()); } } ); @@ -399,9 +399,9 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre } storiesFetching = false; //noinspection unchecked - feedStoriesViewModel.getList().postValue((List) feedStoryModels); + feedStoriesViewModel.getList().postValue((List) feedStoryModels); //noinspection unchecked - feedStoriesAdapter.submitList((List) feedStoryModels); + feedStoriesAdapter.submitList((List) feedStoryModels); if (storyListMenu != null) storyListMenu.setVisible(true); updateSwipeRefreshState(); }), Dispatchers.getIO()) diff --git a/app/src/main/java/awais/instagrabber/models/FeedStoryModel.kt b/app/src/main/java/awais/instagrabber/models/FeedStoryModel.kt deleted file mode 100644 index 8040b36a..00000000 --- a/app/src/main/java/awais/instagrabber/models/FeedStoryModel.kt +++ /dev/null @@ -1,20 +0,0 @@ -package awais.instagrabber.models - -import awais.instagrabber.repositories.responses.User -import awais.instagrabber.utils.TextUtils -import java.io.Serializable -import java.util.* - -data class FeedStoryModel( - val storyMediaId: String, - val profileModel: User, - var isFullyRead: Boolean, - val timestamp: Long, - val firstStoryModel: StoryModel?, - val mediaCount: Int, - val isLive: Boolean, - val isBestie: Boolean -) : Serializable { - val dateTime: String - get() = TextUtils.epochSecondToString(timestamp) -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/repositories/StoriesService.kt b/app/src/main/java/awais/instagrabber/repositories/StoriesService.kt index 51f271f4..a55315e9 100644 --- a/app/src/main/java/awais/instagrabber/repositories/StoriesService.kt +++ b/app/src/main/java/awais/instagrabber/repositories/StoriesService.kt @@ -1,6 +1,7 @@ package awais.instagrabber.repositories -import awais.instagrabber.repositories.responses.StoryStickerResponse +import awais.instagrabber.repositories.responses.stories.ReelsTrayResponse +import awais.instagrabber.repositories.responses.stories.StoryStickerResponse import retrofit2.http.* interface StoriesService { @@ -9,7 +10,7 @@ interface StoriesService { suspend fun fetch(@Path("mediaId") mediaId: Long): String @GET("/api/v1/feed/reels_tray/") - suspend fun getFeedStories(): String + suspend fun getFeedStories(): ReelsTrayResponse @GET("/api/v1/highlights/{uid}/highlights_tray/") suspend fun fetchHighlights(@Path("uid") uid: Long): String diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/stories/Broadcast.kt b/app/src/main/java/awais/instagrabber/repositories/responses/stories/Broadcast.kt index 0037d73e..e5172d69 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/stories/Broadcast.kt +++ b/app/src/main/java/awais/instagrabber/repositories/responses/stories/Broadcast.kt @@ -4,7 +4,7 @@ import java.io.Serializable import awais.instagrabber.repositories.responses.User data class Broadcast( - val id: Long?, + val id: String?, val dashPlaybackUrl: String?, val dashAbrPlaybackUrl: String?, // adaptive quality val viewerCount: Double?, // always .0 diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/stories/Story.kt b/app/src/main/java/awais/instagrabber/repositories/responses/stories/Story.kt index 3c2312c1..81e3d0d1 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/stories/Story.kt +++ b/app/src/main/java/awais/instagrabber/repositories/responses/stories/Story.kt @@ -3,14 +3,19 @@ package awais.instagrabber.repositories.responses.stories import java.io.Serializable import awais.instagrabber.repositories.responses.Media import awais.instagrabber.repositories.responses.User +import awais.instagrabber.utils.TextUtils data class Story( - val id: Long?, + val id: String?, val latestReelMedia: Long?, // = timestamp - val seen: Long?, + var seen: Long?, val user: User?, val muted: Boolean?, val hasBestiesMedia: Boolean?, val mediaCount: Int?, - val items: List? // may be null -) : Serializable \ No newline at end of file + val items: List?, // may be null + val broadcast: Broadcast? // does not naturally occur +) : Serializable { + val dateTime: String + get() = if (latestReelMedia != null) TextUtils.epochSecondToString(latestReelMedia) else "" +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryMedia.kt b/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryMedia.kt index 4fa49d3d..b9374cdc 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryMedia.kt +++ b/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryMedia.kt @@ -3,6 +3,7 @@ package awais.instagrabber.repositories.responses.stories import awais.instagrabber.models.enums.MediaItemType import awais.instagrabber.utils.TextUtils import awais.instagrabber.repositories.responses.ImageVersions2 +import awais.instagrabber.repositories.responses.Media import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.MediaCandidate import java.io.Serializable diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryStickerResponse.kt b/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryStickerResponse.kt index 8ac2f4a9..9a765ec2 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryStickerResponse.kt +++ b/app/src/main/java/awais/instagrabber/repositories/responses/stories/StoryStickerResponse.kt @@ -1,20 +1,3 @@ -package awais.instagrabber.repositories.responses; +package awais.instagrabber.repositories.responses.stories -public class StoryStickerResponse { - private final String status; - - public StoryStickerResponse(final String status) { - this.status = status; - } - - public String getStatus() { - return status; - } - - @Override - public String toString() { - return "StoryStickerResponse{" + - "status='" + status + '\'' + - '}'; - } -} +data class StoryStickerResponse(val status: String?) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java b/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java index 530dd208..5c625a6f 100644 --- a/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java +++ b/app/src/main/java/awais/instagrabber/utils/ResponseBodyUtils.java @@ -21,6 +21,7 @@ import awais.instagrabber.models.stickers.QuestionModel; import awais.instagrabber.models.stickers.QuizModel; import awais.instagrabber.models.stickers.SliderModel; import awais.instagrabber.models.stickers.SwipeUpModel; +import awais.instagrabber.repositories.responses.stories.StoryMedia; import awais.instagrabber.repositories.responses.Caption; import awais.instagrabber.repositories.responses.FriendshipStatus; import awais.instagrabber.repositories.responses.ImageVersions2; @@ -406,27 +407,38 @@ public final class ResponseBodyUtils { return model; } - public static String getThumbUrl(final Media media) { + public static String getThumbUrl(final Object media) { return getImageCandidate(media, CandidateType.THUMBNAIL); } - public static String getImageUrl(final Media media) { + public static String getImageUrl(final Object media) { return getImageCandidate(media, CandidateType.DOWNLOAD); } - private static String getImageCandidate(final Media media, final CandidateType type) { - if (media == null) return null; - final ImageVersions2 imageVersions2 = media.getImageVersions2(); + private static String getImageCandidate(final Object rawMedia, final CandidateType type) { + final ImageVersions2 imageVersions2; + final int originalWidth, originalHeight; + if (rawMedia instanceof StoryMedia) { + imageVersions2 = ((StoryMedia) rawMedia).getImageVersions2(); + originalWidth = ((StoryMedia) rawMedia).getOriginalWidth(); + originalHeight = ((StoryMedia) rawMedia).getOriginalHeight(); + } + else if (rawMedia instanceof Media) { + imageVersions2 = ((Media) rawMedia).getImageVersions2(); + originalWidth = ((Media) rawMedia).getOriginalWidth(); + originalHeight = ((Media) rawMedia).getOriginalHeight(); + } + else return null; if (imageVersions2 == null) return null; final List candidates = imageVersions2.getCandidates(); if (candidates == null || candidates.isEmpty()) return null; - final boolean isSquare = Integer.compare(media.getOriginalWidth(), media.getOriginalHeight()) == 0; + final boolean isSquare = Integer.compare(originalWidth, originalHeight) == 0; final List sortedCandidates = candidates.stream() .sorted((c1, c2) -> Integer.compare(c2.getWidth(), c1.getWidth())) .collect(Collectors.toList()); final List filteredCandidates = sortedCandidates.stream() .filter(c -> - c.getWidth() <= media.getOriginalWidth() + c.getWidth() <= originalWidth && c.getWidth() <= type.getValue() && (isSquare || Integer .compare(c.getWidth(), c.getHeight()) != 0) diff --git a/app/src/main/java/awais/instagrabber/viewmodels/FeedStoriesViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/FeedStoriesViewModel.java index f4bd3b41..6387d184 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/FeedStoriesViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/FeedStoriesViewModel.java @@ -6,12 +6,12 @@ import androidx.lifecycle.ViewModel; import java.util.ArrayList; import java.util.List; -import awais.instagrabber.models.FeedStoryModel; +import awais.instagrabber.repositories.responses.stories.Story; public class FeedStoriesViewModel extends ViewModel { - private MutableLiveData> list; + private MutableLiveData> list; - public MutableLiveData> getList() { + public MutableLiveData> getList() { if (list == null) { list = new MutableLiveData<>(); } diff --git a/app/src/main/java/awais/instagrabber/webservices/StoriesRepository.kt b/app/src/main/java/awais/instagrabber/webservices/StoriesRepository.kt index 7235ace1..89603777 100644 --- a/app/src/main/java/awais/instagrabber/webservices/StoriesRepository.kt +++ b/app/src/main/java/awais/instagrabber/webservices/StoriesRepository.kt @@ -1,19 +1,16 @@ package awais.instagrabber.webservices -import android.util.Log import awais.instagrabber.fragments.settings.PreferenceKeys -import awais.instagrabber.models.FeedStoryModel import awais.instagrabber.models.HighlightModel import awais.instagrabber.models.StoryModel import awais.instagrabber.repositories.StoriesService import awais.instagrabber.repositories.requests.StoryViewerOptions -import awais.instagrabber.repositories.responses.StoryStickerResponse -import awais.instagrabber.repositories.responses.User +import awais.instagrabber.repositories.responses.stories.Story +import awais.instagrabber.repositories.responses.stories.StoryStickerResponse import awais.instagrabber.utils.Constants import awais.instagrabber.utils.ResponseBodyUtils import awais.instagrabber.utils.TextUtils.isEmpty import awais.instagrabber.utils.Utils -import awais.instagrabber.utils.extensions.TAG import awais.instagrabber.webservices.RetrofitFactory.retrofit import org.json.JSONArray import org.json.JSONObject @@ -27,76 +24,29 @@ open class StoriesRepository(private val service: StoriesService) { return ResponseBodyUtils.parseStoryItem(itemJson, false, null) } - suspend fun getFeedStories(): List { + suspend fun getFeedStories(): List { val response = service.getFeedStories() - return parseStoriesBody(response) - } - - private fun parseStoriesBody(body: String): List { - val feedStoryModels: MutableList = ArrayList() - val feedStoriesReel = JSONObject(body).getJSONArray("tray") - for (i in 0 until feedStoriesReel.length()) { - val node = feedStoriesReel.getJSONObject(i) - if (node.optBoolean("hide_from_feed_unit") && Utils.settingsHelper.getBoolean(PreferenceKeys.HIDE_MUTED_REELS)) continue - val userJson = node.getJSONObject(if (node.has("user")) "user" else "owner") - try { - val user = User( - userJson.getLong("pk"), - userJson.getString("username"), - userJson.optString("full_name"), - userJson.optBoolean("is_private"), - userJson.getString("profile_pic_url"), - userJson.optBoolean("is_verified") - ) - val timestamp = node.getLong("latest_reel_media") - val fullyRead = !node.isNull("seen") && node.getLong("seen") == timestamp - val itemJson = if (node.has("items")) node.getJSONArray("items").optJSONObject(0) else null - var firstStoryModel: StoryModel? = null - if (itemJson != null) { - firstStoryModel = ResponseBodyUtils.parseStoryItem(itemJson, false, null) - } - feedStoryModels.add( - FeedStoryModel( - node.getString("id"), - user, - fullyRead, - timestamp, - firstStoryModel, - node.getInt("media_count"), - false, - node.optBoolean("has_besties_media") + val result = response.tray?.toMutableList() ?: mutableListOf() + if (response.broadcasts != null) { + val length = response.broadcasts.size + for (i in 0 until length) { + val broadcast = response.broadcasts.get(i) + result.add( + Story( + broadcast.id, + broadcast.publishedTime, + 0L, + broadcast.broadcastOwner, + broadcast.muted, + false, // unclear + 1, + null, + broadcast ) ) - } catch (e: Exception) { - Log.e(TAG, "parseStoriesBody: ", e) - } // to cover promotional reels with non-long user pk's - } - val broadcasts = JSONObject(body).getJSONArray("broadcasts") - for (i in 0 until broadcasts.length()) { - val node = broadcasts.getJSONObject(i) - val userJson = node.getJSONObject("broadcast_owner") - val user = User( - userJson.getLong("pk"), - userJson.getString("username"), - userJson.optString("full_name"), - userJson.optBoolean("is_private"), - userJson.getString("profile_pic_url"), - userJson.optBoolean("is_verified") - ) - feedStoryModels.add( - FeedStoryModel( - node.getString("id"), - user, - false, - node.getLong("published_time"), - ResponseBodyUtils.parseBroadcastItem(node), - 1, - isLive = true, - isBestie = false - ) - ) + } } - return sort(feedStoryModels) + return sort(result.toList()) } open suspend fun fetchHighlights(profileId: Long): List { @@ -299,12 +249,13 @@ open class StoriesRepository(private val service: StoriesService) { return builder.toString() } - private fun sort(list: List): List { + private fun sort(list: List): List { val listCopy = ArrayList(list) listCopy.sortWith { o1, o2 -> - when (Utils.settingsHelper.getString(PreferenceKeys.STORY_SORT)) { - "1" -> return@sortWith o2.timestamp.compareTo(o1.timestamp) - "2" -> return@sortWith o1.timestamp.compareTo(o2.timestamp) + if (o1.latestReelMedia == null || o2.latestReelMedia == null) return@sortWith 0 + else when (Utils.settingsHelper.getString(PreferenceKeys.STORY_SORT)) { + "1" -> return@sortWith o2.latestReelMedia.compareTo(o1.latestReelMedia) + "2" -> return@sortWith o1.latestReelMedia.compareTo(o2.latestReelMedia) else -> return@sortWith 0 } } diff --git a/app/src/main/res/layout/fragment_story_viewer.xml b/app/src/main/res/layout/fragment_story_viewer.xml index 4495cab6..e56f5a7a 100644 --- a/app/src/main/res/layout/fragment_story_viewer.xml +++ b/app/src/main/res/layout/fragment_story_viewer.xml @@ -133,7 +133,7 @@ android:id="@+id/btnBackward" style="@style/Widget.MaterialComponents.Button.TextButton" android:layout_width="40dp" - android:layout_height="0dp" + android:layout_height="@dimen/story_item_height" android:visibility="visible" app:icon="@drawable/exo_ic_skip_previous" app:iconGravity="textStart" @@ -146,7 +146,7 @@