mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-28 17:37:29 +00:00
Add user story and highlights fetch logic
This commit is contained in:
parent
a713a72e07
commit
50c120eb75
@ -1,14 +1,13 @@
|
||||
package awais.instagrabber.models
|
||||
|
||||
import awais.instagrabber.utils.TextUtils
|
||||
import java.util.*
|
||||
|
||||
data class HighlightModel(
|
||||
val title: String?,
|
||||
val id: String,
|
||||
val thumbnailUrl: String,
|
||||
val timestamp: Long,
|
||||
val mediaCount: Int
|
||||
val title: String? = null,
|
||||
val id: String = "",
|
||||
val thumbnailUrl: String = "",
|
||||
val timestamp: Long = 0,
|
||||
val mediaCount: Int = 0,
|
||||
) {
|
||||
val dateTime: String
|
||||
get() = TextUtils.epochSecondToString(timestamp)
|
||||
|
@ -5,14 +5,14 @@ import awais.instagrabber.models.stickers.*
|
||||
import java.io.Serializable
|
||||
|
||||
data class StoryModel(
|
||||
val storyMediaId: String?,
|
||||
val storyUrl: String?,
|
||||
var thumbnail: String?,
|
||||
val itemType: MediaItemType?,
|
||||
val timestamp: Long,
|
||||
val username: String?,
|
||||
val userId: Long,
|
||||
val canReply: Boolean
|
||||
val storyMediaId: String? = null,
|
||||
val storyUrl: String? = null,
|
||||
var thumbnail: String? = null,
|
||||
val itemType: MediaItemType? = null,
|
||||
val timestamp: Long = 0,
|
||||
val username: String? = null,
|
||||
val userId: Long = 0,
|
||||
val canReply: Boolean = false,
|
||||
) : Serializable {
|
||||
var videoUrl: String? = null
|
||||
var tappableShortCode: String? = null
|
||||
|
@ -8,8 +8,11 @@ import awais.instagrabber.db.entities.Favorite
|
||||
import awais.instagrabber.db.repositories.AccountRepository
|
||||
import awais.instagrabber.db.repositories.FavoriteRepository
|
||||
import awais.instagrabber.managers.DirectMessagesManager
|
||||
import awais.instagrabber.models.HighlightModel
|
||||
import awais.instagrabber.models.Resource
|
||||
import awais.instagrabber.models.StoryModel
|
||||
import awais.instagrabber.models.enums.FavoriteType
|
||||
import awais.instagrabber.repositories.requests.StoryViewerOptions
|
||||
import awais.instagrabber.repositories.responses.User
|
||||
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
|
||||
import awais.instagrabber.utils.ControlledRunner
|
||||
@ -22,7 +25,7 @@ class ProfileFragmentViewModel(
|
||||
state: SavedStateHandle,
|
||||
userRepository: UserRepository,
|
||||
friendshipRepository: FriendshipRepository,
|
||||
storiesRepository: StoriesRepository,
|
||||
private val storiesRepository: StoriesRepository,
|
||||
mediaRepository: MediaRepository,
|
||||
graphQLRepository: GraphQLRepository,
|
||||
accountRepository: AccountRepository,
|
||||
@ -61,27 +64,21 @@ class ProfileFragmentViewModel(
|
||||
|
||||
private val profileFetchControlledRunner = ControlledRunner<User?>()
|
||||
val profile: LiveData<Resource<User?>> = currentUserAndStateUsernameLiveData.switchMap {
|
||||
val (userResource, stateUsernameResource) = it
|
||||
val (currentUserResource, stateUsernameResource) = it
|
||||
liveData<Resource<User?>>(context = viewModelScope.coroutineContext + ioDispatcher) {
|
||||
if (userResource.status == Resource.Status.LOADING || stateUsernameResource.status == Resource.Status.LOADING) {
|
||||
if (currentUserResource.status == Resource.Status.LOADING || stateUsernameResource.status == Resource.Status.LOADING) {
|
||||
emit(Resource.loading(null))
|
||||
return@liveData
|
||||
}
|
||||
val user = userResource.data
|
||||
val currentUser = currentUserResource.data
|
||||
val stateUsername = stateUsernameResource.data
|
||||
if (stateUsername.isNullOrBlank()) {
|
||||
emit(Resource.success(user))
|
||||
emit(Resource.success(currentUser))
|
||||
return@liveData
|
||||
}
|
||||
try {
|
||||
val fetchedUser = profileFetchControlledRunner.cancelPreviousThenRun {
|
||||
return@cancelPreviousThenRun if (user != null) {
|
||||
val tempUser = userRepository.getUsernameInfo(stateUsername) // logged in
|
||||
tempUser.friendshipStatus = userRepository.getUserFriendship(tempUser.pk)
|
||||
return@cancelPreviousThenRun tempUser
|
||||
} else {
|
||||
graphQLRepository.fetchUser(stateUsername) // anonymous
|
||||
}
|
||||
return@cancelPreviousThenRun fetchUser(currentUser, userRepository, stateUsername, graphQLRepository)
|
||||
}
|
||||
emit(Resource.success(fetchedUser))
|
||||
if (fetchedUser != null) {
|
||||
@ -94,6 +91,81 @@ class ProfileFragmentViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private val storyFetchControlledRunner = ControlledRunner<List<StoryModel>?>()
|
||||
val userStories: LiveData<Resource<List<StoryModel>?>> = profile.switchMap { userResource ->
|
||||
liveData<Resource<List<StoryModel>?>>(context = viewModelScope.coroutineContext + ioDispatcher) {
|
||||
// don't fetch if not logged in
|
||||
if (isLoggedIn.value != true) {
|
||||
emit(Resource.success(null))
|
||||
return@liveData
|
||||
}
|
||||
if (userResource.status == Resource.Status.LOADING) {
|
||||
emit(Resource.loading(null))
|
||||
return@liveData
|
||||
}
|
||||
val user = userResource.data
|
||||
if (user == null) {
|
||||
emit(Resource.success(null))
|
||||
return@liveData
|
||||
}
|
||||
try {
|
||||
val fetchedStories = storyFetchControlledRunner.cancelPreviousThenRun { fetchUserStory(user) }
|
||||
emit(Resource.success(fetchedStories))
|
||||
} catch (e: Exception) {
|
||||
emit(Resource.error(e.message, null))
|
||||
Log.e(TAG, "fetching story: ", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val highlightsFetchControlledRunner = ControlledRunner<List<HighlightModel>?>()
|
||||
val userHighlights: LiveData<Resource<List<HighlightModel>?>> = profile.switchMap { userResource ->
|
||||
liveData<Resource<List<HighlightModel>?>>(context = viewModelScope.coroutineContext + ioDispatcher) {
|
||||
// don't fetch if not logged in
|
||||
if (isLoggedIn.value != true) {
|
||||
emit(Resource.success(null))
|
||||
return@liveData
|
||||
}
|
||||
if (userResource.status == Resource.Status.LOADING) {
|
||||
emit(Resource.loading(null))
|
||||
return@liveData
|
||||
}
|
||||
val user = userResource.data
|
||||
if (user == null) {
|
||||
emit(Resource.success(null))
|
||||
return@liveData
|
||||
}
|
||||
try {
|
||||
val fetchedHighlights = highlightsFetchControlledRunner.cancelPreviousThenRun { fetchUserHighlights(user) }
|
||||
emit(Resource.success(fetchedHighlights))
|
||||
} catch (e: Exception) {
|
||||
emit(Resource.error(e.message, null))
|
||||
Log.e(TAG, "fetching story: ", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchUser(
|
||||
currentUser: User?,
|
||||
userRepository: UserRepository,
|
||||
stateUsername: String,
|
||||
graphQLRepository: GraphQLRepository
|
||||
) = if (currentUser != null) {
|
||||
// logged in
|
||||
val tempUser = userRepository.getUsernameInfo(stateUsername)
|
||||
tempUser.friendshipStatus = userRepository.getUserFriendship(tempUser.pk)
|
||||
tempUser
|
||||
} else {
|
||||
// anonymous
|
||||
graphQLRepository.fetchUser(stateUsername)
|
||||
}
|
||||
|
||||
private suspend fun fetchUserStory(fetchedUser: User): List<StoryModel> = storiesRepository.getUserStory(
|
||||
StoryViewerOptions.forUser(fetchedUser.pk, fetchedUser.fullName)
|
||||
)
|
||||
|
||||
private suspend fun fetchUserHighlights(fetchedUser: User): List<HighlightModel> = storiesRepository.fetchHighlights(fetchedUser.pk)
|
||||
|
||||
private suspend fun checkAndInsertFavorite(fetchedUser: User) {
|
||||
try {
|
||||
val favorite = favoriteRepository.getFavorite(fetchedUser.username, FavoriteType.USER)
|
||||
|
@ -19,7 +19,7 @@ import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
class StoriesRepository(private val service: StoriesService) {
|
||||
open class StoriesRepository(private val service: StoriesService) {
|
||||
|
||||
suspend fun fetch(mediaId: Long): StoryModel {
|
||||
val response = service.fetch(mediaId)
|
||||
@ -99,7 +99,7 @@ class StoriesRepository(private val service: StoriesService) {
|
||||
return sort(feedStoryModels)
|
||||
}
|
||||
|
||||
suspend fun fetchHighlights(profileId: Long): List<HighlightModel> {
|
||||
open suspend fun fetchHighlights(profileId: Long): List<HighlightModel> {
|
||||
val response = service.fetchHighlights(profileId)
|
||||
val highlightsReel = JSONObject(response).getJSONArray("tray")
|
||||
val length = highlightsReel.length()
|
||||
@ -150,7 +150,7 @@ class StoriesRepository(private val service: StoriesService) {
|
||||
return ArchiveFetchResponse(highlightModels, data.getBoolean("more_available"), data.getString("max_id"))
|
||||
}
|
||||
|
||||
suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> {
|
||||
open suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> {
|
||||
val url = buildUrl(options) ?: return emptyList()
|
||||
val response = service.getUserStory(url)
|
||||
val isLocOrHashtag = options.type == StoryViewerOptions.Type.LOCATION || options.type == StoryViewerOptions.Type.HASHTAG
|
||||
|
@ -17,9 +17,7 @@ open class UserServiceAdapter : UserService {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun getUserFriendship(uid: Long): FriendshipStatus {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
override suspend fun getUserFriendship(uid: Long): FriendshipStatus = FriendshipStatus()
|
||||
|
||||
override suspend fun search(timezoneOffset: Float, query: String): UserSearchResponse {
|
||||
TODO("Not yet implemented")
|
||||
|
@ -11,8 +11,11 @@ import awais.instagrabber.db.entities.Favorite
|
||||
import awais.instagrabber.db.repositories.AccountRepository
|
||||
import awais.instagrabber.db.repositories.FavoriteRepository
|
||||
import awais.instagrabber.getOrAwaitValue
|
||||
import awais.instagrabber.models.HighlightModel
|
||||
import awais.instagrabber.models.Resource
|
||||
import awais.instagrabber.models.StoryModel
|
||||
import awais.instagrabber.models.enums.FavoriteType
|
||||
import awais.instagrabber.repositories.requests.StoryViewerOptions
|
||||
import awais.instagrabber.repositories.responses.FriendshipStatus
|
||||
import awais.instagrabber.repositories.responses.User
|
||||
import awais.instagrabber.webservices.*
|
||||
@ -282,4 +285,51 @@ internal class ProfileFragmentViewModelTest {
|
||||
assertEquals(true, viewModel.isFavorite.getOrAwaitValue())
|
||||
assertTrue(updateFavoriteCalled)
|
||||
}
|
||||
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@Test
|
||||
fun `should fetch user stories and highlights when logged in`() {
|
||||
val state = SavedStateHandle(
|
||||
mutableMapOf<String, Any?>(
|
||||
"username" to testPublicUser.username
|
||||
)
|
||||
)
|
||||
val testUserStories = listOf(StoryModel())
|
||||
val testUserHighlights = listOf(HighlightModel())
|
||||
val userRepository = object : UserRepository(UserServiceAdapter()) {
|
||||
override suspend fun getUsernameInfo(username: String): User = testPublicUser
|
||||
}
|
||||
val storiesRepository = object : StoriesRepository(StoriesServiceAdapter()) {
|
||||
override suspend fun getUserStory(options: StoryViewerOptions): List<StoryModel> = testUserStories
|
||||
override suspend fun fetchHighlights(profileId: Long): List<HighlightModel> = testUserHighlights
|
||||
}
|
||||
val viewModel = ProfileFragmentViewModel(
|
||||
state,
|
||||
userRepository,
|
||||
FriendshipRepository(FriendshipServiceAdapter()),
|
||||
storiesRepository,
|
||||
MediaRepository(MediaServiceAdapter()),
|
||||
GraphQLRepository(GraphQLServiceAdapter()),
|
||||
AccountRepository(AccountDataSource(AccountDaoAdapter())),
|
||||
FavoriteRepository(FavoriteDataSource(FavoriteDaoAdapter())),
|
||||
coroutineScope.dispatcher,
|
||||
)
|
||||
viewModel.setCurrentUser(Resource.success(User()))
|
||||
assertEquals(true, viewModel.isLoggedIn.getOrAwaitValue())
|
||||
var profile = viewModel.profile.getOrAwaitValue()
|
||||
while (profile.status == Resource.Status.LOADING) {
|
||||
profile = viewModel.profile.getOrAwaitValue()
|
||||
}
|
||||
var userStories = viewModel.userStories.getOrAwaitValue()
|
||||
while (userStories.status == Resource.Status.LOADING) {
|
||||
userStories = viewModel.userStories.getOrAwaitValue()
|
||||
}
|
||||
assertEquals(testUserStories, userStories.data)
|
||||
var userHighlights = viewModel.userHighlights.getOrAwaitValue()
|
||||
while (userHighlights.status == Resource.Status.LOADING) {
|
||||
userHighlights = viewModel.userHighlights.getOrAwaitValue()
|
||||
}
|
||||
assertEquals(testUserHighlights, userHighlights.data)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user