convert HighlightModel usages (as highlights) to Story

This commit is contained in:
Austin Huang 2021-06-29 10:28:32 -04:00
parent dbf0c66b41
commit f7ce2eeea2
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
14 changed files with 48 additions and 52 deletions

View File

@ -9,20 +9,20 @@ import androidx.recyclerview.widget.ListAdapter;
import awais.instagrabber.adapters.viewholder.HighlightViewHolder; import awais.instagrabber.adapters.viewholder.HighlightViewHolder;
import awais.instagrabber.databinding.ItemHighlightBinding; import awais.instagrabber.databinding.ItemHighlightBinding;
import awais.instagrabber.models.HighlightModel; import awais.instagrabber.repositories.responses.stories.Story;
public final class HighlightsAdapter extends ListAdapter<HighlightModel, HighlightViewHolder> { public final class HighlightsAdapter extends ListAdapter<Story, HighlightViewHolder> {
private final OnHighlightClickListener clickListener; private final OnHighlightClickListener clickListener;
private static final DiffUtil.ItemCallback<HighlightModel> diffCallback = new DiffUtil.ItemCallback<HighlightModel>() { private static final DiffUtil.ItemCallback<Story> diffCallback = new DiffUtil.ItemCallback<Story>() {
@Override @Override
public boolean areItemsTheSame(@NonNull final HighlightModel oldItem, @NonNull final HighlightModel newItem) { public boolean areItemsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
return oldItem.getId().equals(newItem.getId()); return oldItem.getId().equals(newItem.getId());
} }
@Override @Override
public boolean areContentsTheSame(@NonNull final HighlightModel oldItem, @NonNull final HighlightModel newItem) { public boolean areContentsTheSame(@NonNull final Story oldItem, @NonNull final Story newItem) {
return oldItem.getId().equals(newItem.getId()); return oldItem.getId().equals(newItem.getId());
} }
}; };
@ -42,7 +42,7 @@ public final class HighlightsAdapter extends ListAdapter<HighlightModel, Highlig
@Override @Override
public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) { public void onBindViewHolder(@NonNull final HighlightViewHolder holder, final int position) {
final HighlightModel highlightModel = getItem(position); final Story highlightModel = getItem(position);
if (clickListener != null) { if (clickListener != null) {
holder.itemView.setOnClickListener(v -> clickListener.onHighlightClick(highlightModel, position)); holder.itemView.setOnClickListener(v -> clickListener.onHighlightClick(highlightModel, position));
} }
@ -50,6 +50,6 @@ public final class HighlightsAdapter extends ListAdapter<HighlightModel, Highlig
} }
public interface OnHighlightClickListener { public interface OnHighlightClickListener {
void onHighlightClick(final HighlightModel model, final int position); void onHighlightClick(final Story model, final int position);
} }
} }

View File

@ -3,7 +3,7 @@ package awais.instagrabber.adapters.viewholder;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import awais.instagrabber.databinding.ItemHighlightBinding; import awais.instagrabber.databinding.ItemHighlightBinding;
import awais.instagrabber.models.HighlightModel; import awais.instagrabber.repositories.responses.stories.Story;
public final class HighlightViewHolder extends RecyclerView.ViewHolder { public final class HighlightViewHolder extends RecyclerView.ViewHolder {
@ -14,10 +14,10 @@ public final class HighlightViewHolder extends RecyclerView.ViewHolder {
this.binding = binding; this.binding = binding;
} }
public void bind(final HighlightModel model) { public void bind(final Story model) {
if (model == null) return; if (model == null) return;
binding.title.setText(model.getTitle()); binding.title.setText(model.getTitle());
binding.icon.setImageURI(model.getThumbnailUrl()); binding.icon.setImageURI(model.getCoverMedia().getCroppedImageVersion().getUrl());
// binding.getRoot().setOnClickListener(v -> { // binding.getRoot().setOnClickListener(v -> {
// if (listener == null) return; // if (listener == null) return;
// listener.onFeedStoryClick(model, position); // listener.onFeedStoryClick(model, position);

View File

@ -736,12 +736,12 @@ public class StoryViewerFragment extends Fragment {
switch (type) { switch (type) {
case HIGHLIGHT: { case HIGHLIGHT: {
final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel; final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
final List<HighlightModel> models = highlightsViewModel.getList().getValue(); final List<Story> models = highlightsViewModel.getList().getValue();
if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) { if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
return; return;
} }
final HighlightModel model = models.get(currentFeedStoryIndex); final Story model = models.get(currentFeedStoryIndex);
currentStoryMediaId = model.getId(); currentStoryMediaId = model.getId();
fetchOptions = StoryViewerOptions.forHighlight(model.getId()); fetchOptions = StoryViewerOptions.forHighlight(model.getId());
highlightTitle = model.getTitle(); highlightTitle = model.getTitle();

View File

@ -73,7 +73,6 @@ import awais.instagrabber.fragments.UserSearchFragment;
import awais.instagrabber.fragments.UserSearchFragmentDirections; import awais.instagrabber.fragments.UserSearchFragmentDirections;
import awais.instagrabber.managers.DirectMessagesManager; import awais.instagrabber.managers.DirectMessagesManager;
import awais.instagrabber.managers.InboxManager; import awais.instagrabber.managers.InboxManager;
import awais.instagrabber.models.HighlightModel;
import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.FavoriteType; import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.models.enums.PostItemType;
@ -84,6 +83,7 @@ import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.UserProfileContextLink; import awais.instagrabber.repositories.responses.UserProfileContextLink;
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
import awais.instagrabber.repositories.responses.stories.Story;
import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.CookieUtils;
@ -1121,7 +1121,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (highlightModels != null) { if (highlightModels != null) {
profileDetailsBinding.highlightsList.setVisibility(View.VISIBLE); profileDetailsBinding.highlightsList.setVisibility(View.VISIBLE);
//noinspection unchecked //noinspection unchecked
highlightsViewModel.getList().postValue((List<HighlightModel>) highlightModels); highlightsViewModel.getList().postValue((List<Story>) highlightModels);
} else { } else {
profileDetailsBinding.highlightsList.setVisibility(View.GONE); profileDetailsBinding.highlightsList.setVisibility(View.GONE);
} }

View File

@ -13,7 +13,7 @@ interface StoriesService {
suspend fun getFeedStories(): ReelsTrayResponse suspend fun getFeedStories(): ReelsTrayResponse
@GET("/api/v1/highlights/{uid}/highlights_tray/") @GET("/api/v1/highlights/{uid}/highlights_tray/")
suspend fun fetchHighlights(@Path("uid") uid: Long): String suspend fun fetchHighlights(@Path("uid") uid: Long): ReelsTrayResponse
@GET("/api/v1/archive/reel/day_shells/") @GET("/api/v1/archive/reel/day_shells/")
suspend fun fetchArchive(@QueryMap queryParams: Map<String, String>): String suspend fun fetchArchive(@QueryMap queryParams: Map<String, String>): String

View File

@ -1,5 +0,0 @@
package awais.instagrabber.repositories.responses
import java.io.Serializable
data class HdProfilePicUrlInfo(val url: String, private val width: Int, private val height: Int) : Serializable

View File

@ -0,0 +1,5 @@
package awais.instagrabber.repositories.responses
import java.io.Serializable
data class ImageUrl(val url: String, private val width: Int, private val height: Int) : Serializable

View File

@ -27,7 +27,7 @@ data class User @JvmOverloads constructor(
val externalUrl: String? = null, val externalUrl: String? = null,
val usertagsCount: Long = 0, val usertagsCount: Long = 0,
val publicEmail: String? = null, val publicEmail: String? = null,
val hdProfilePicUrlInfo: HdProfilePicUrlInfo? = null, val hdProfilePicUrlInfo: ImageUrl? = null,
val profileContext: String? = null, // "also followed by" your friends val profileContext: String? = null, // "also followed by" your friends
val profileContextLinksWithUserIds: List<UserProfileContextLink>? = null, // ^ val profileContextLinksWithUserIds: List<UserProfileContextLink>? = null, // ^
val socialContext: String? = null, // AYML val socialContext: String? = null, // AYML

View File

@ -0,0 +1,5 @@
package awais.instagrabber.repositories.responses.stories
import awais.instagrabber.repositories.responses.ImageUrl
data class CoverMedia(val croppedImageVersion: ImageUrl)

View File

@ -1,19 +1,24 @@
package awais.instagrabber.repositories.responses.stories package awais.instagrabber.repositories.responses.stories
import java.io.Serializable import java.io.Serializable
import awais.instagrabber.repositories.responses.Media
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.utils.TextUtils import awais.instagrabber.utils.TextUtils
data class Story( data class Story(
// universal
val id: String?, val id: String?,
val latestReelMedia: Long?, // = timestamp val latestReelMedia: Long?, // = timestamp
var seen: Long?, var seen: Long?,
val user: User?, val user: User?,
// for stories
val mediaCount: Int?,
val muted: Boolean?, val muted: Boolean?,
val hasBestiesMedia: Boolean?, val hasBestiesMedia: Boolean?,
val mediaCount: Int?,
val items: List<StoryMedia>?, // may be null val items: List<StoryMedia>?, // may be null
// for highlights
val coverMedia: CoverMedia?,
val title: String?,
// invented fields
val broadcast: Broadcast? // does not naturally occur val broadcast: Broadcast? // does not naturally occur
) : Serializable { ) : Serializable {
val dateTime: String val dateTime: String

View File

@ -5,12 +5,12 @@ import androidx.lifecycle.ViewModel;
import java.util.List; import java.util.List;
import awais.instagrabber.models.HighlightModel; import awais.instagrabber.repositories.responses.stories.Story;
public class HighlightsViewModel extends ViewModel { public class HighlightsViewModel extends ViewModel {
private MutableLiveData<List<HighlightModel>> list; private MutableLiveData<List<Story>> list;
public MutableLiveData<List<HighlightModel>> getList() { public MutableLiveData<List<Story>> getList() {
if (list == null) { if (list == null) {
list = new MutableLiveData<>(); list = new MutableLiveData<>();
} }

View File

@ -8,7 +8,6 @@ import awais.instagrabber.db.entities.Favorite
import awais.instagrabber.db.repositories.AccountRepository import awais.instagrabber.db.repositories.AccountRepository
import awais.instagrabber.db.repositories.FavoriteRepository import awais.instagrabber.db.repositories.FavoriteRepository
import awais.instagrabber.managers.DirectMessagesManager import awais.instagrabber.managers.DirectMessagesManager
import awais.instagrabber.models.HighlightModel
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.models.StoryModel import awais.instagrabber.models.StoryModel
import awais.instagrabber.models.enums.BroadcastItemType import awais.instagrabber.models.enums.BroadcastItemType
@ -16,6 +15,7 @@ import awais.instagrabber.models.enums.FavoriteType
import awais.instagrabber.repositories.requests.StoryViewerOptions import awais.instagrabber.repositories.requests.StoryViewerOptions
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
import awais.instagrabber.repositories.responses.stories.Story
import awais.instagrabber.utils.ControlledRunner import awais.instagrabber.utils.ControlledRunner
import awais.instagrabber.utils.extensions.TAG import awais.instagrabber.utils.extensions.TAG
import awais.instagrabber.webservices.* import awais.instagrabber.webservices.*
@ -119,9 +119,9 @@ class ProfileFragmentViewModel(
} }
} }
private val highlightsFetchControlledRunner = ControlledRunner<List<HighlightModel>?>() private val highlightsFetchControlledRunner = ControlledRunner<List<Story>?>()
val userHighlights: LiveData<Resource<List<HighlightModel>?>> = profile.switchMap { userResource -> val userHighlights: LiveData<Resource<List<Story>?>> = profile.switchMap { userResource ->
liveData<Resource<List<HighlightModel>?>>(context = viewModelScope.coroutineContext + ioDispatcher) { liveData<Resource<List<Story>?>>(context = viewModelScope.coroutineContext + ioDispatcher) {
// don't fetch if not logged in // don't fetch if not logged in
if (isLoggedIn.value != true) { if (isLoggedIn.value != true) {
emit(Resource.success(null)) emit(Resource.success(null))
@ -165,7 +165,7 @@ class ProfileFragmentViewModel(
StoryViewerOptions.forUser(fetchedUser.pk, fetchedUser.fullName) StoryViewerOptions.forUser(fetchedUser.pk, fetchedUser.fullName)
) )
private suspend fun fetchUserHighlights(fetchedUser: User): List<HighlightModel> = storiesRepository.fetchHighlights(fetchedUser.pk) private suspend fun fetchUserHighlights(fetchedUser: User): List<Story> = storiesRepository.fetchHighlights(fetchedUser.pk)
private suspend fun checkAndInsertFavorite(fetchedUser: User) { private suspend fun checkAndInsertFavorite(fetchedUser: User) {
try { try {

View File

@ -37,9 +37,11 @@ open class StoriesRepository(private val service: StoriesService) {
broadcast.publishedTime, broadcast.publishedTime,
0L, 0L,
broadcast.broadcastOwner, broadcast.broadcastOwner,
1,
broadcast.muted, broadcast.muted,
false, // unclear false, // unclear
1, null,
null,
null, null,
broadcast broadcast
) )
@ -49,25 +51,9 @@ open class StoriesRepository(private val service: StoriesService) {
return sort(result.toList()) return sort(result.toList())
} }
open suspend fun fetchHighlights(profileId: Long): List<HighlightModel> { open suspend fun fetchHighlights(profileId: Long): List<Story> {
val response = service.fetchHighlights(profileId) val response = service.fetchHighlights(profileId)
val highlightsReel = JSONObject(response).getJSONArray("tray") val highlightModels = response.tray ?: listOf()
val length = highlightsReel.length()
val highlightModels: MutableList<HighlightModel> = ArrayList()
for (i in 0 until length) {
val highlightNode = highlightsReel.getJSONObject(i)
highlightModels.add(
HighlightModel(
highlightNode.getString("title"),
highlightNode.getString(Constants.EXTRAS_ID),
highlightNode.getJSONObject("cover_media")
.getJSONObject("cropped_image_version")
.getString("url"),
highlightNode.getLong("latest_reel_media"),
highlightNode.getInt("media_count")
)
)
}
return highlightModels return highlightModels
} }

View File

@ -11,13 +11,13 @@ import awais.instagrabber.db.entities.Favorite
import awais.instagrabber.db.repositories.AccountRepository import awais.instagrabber.db.repositories.AccountRepository
import awais.instagrabber.db.repositories.FavoriteRepository import awais.instagrabber.db.repositories.FavoriteRepository
import awais.instagrabber.getOrAwaitValue import awais.instagrabber.getOrAwaitValue
import awais.instagrabber.models.HighlightModel
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.models.StoryModel import awais.instagrabber.models.StoryModel
import awais.instagrabber.models.enums.FavoriteType import awais.instagrabber.models.enums.FavoriteType
import awais.instagrabber.repositories.requests.StoryViewerOptions import awais.instagrabber.repositories.requests.StoryViewerOptions
import awais.instagrabber.repositories.responses.FriendshipStatus import awais.instagrabber.repositories.responses.FriendshipStatus
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.stories.Story
import awais.instagrabber.webservices.* import awais.instagrabber.webservices.*
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.json.JSONException import org.json.JSONException
@ -296,7 +296,7 @@ internal class ProfileFragmentViewModelTest {
) )
) )
val testUserStories = listOf(StoryModel()) val testUserStories = listOf(StoryModel())
val testUserHighlights = listOf(HighlightModel()) val testUserHighlights = listOf(Story())
val userRepository = object : UserRepository(UserServiceAdapter()) { val userRepository = object : UserRepository(UserServiceAdapter()) {
override suspend fun getUsernameInfo(username: String): User = testPublicUser override suspend fun getUsernameInfo(username: String): User = testPublicUser
} }