1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-14 02:37:30 +00:00

re-implement viewing highlights

This commit is contained in:
Austin Huang 2021-07-06 15:08:10 -04:00
parent 86b6df315c
commit 379468d577
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
4 changed files with 89 additions and 116 deletions

View File

@ -18,7 +18,9 @@ import androidx.appcompat.widget.PopupMenu
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController import androidx.navigation.NavController
@ -29,6 +31,7 @@ import awais.instagrabber.R
import awais.instagrabber.adapters.StoriesAdapter import awais.instagrabber.adapters.StoriesAdapter
import awais.instagrabber.customviews.helpers.SwipeGestureListener import awais.instagrabber.customviews.helpers.SwipeGestureListener
import awais.instagrabber.databinding.FragmentStoryViewerBinding import awais.instagrabber.databinding.FragmentStoryViewerBinding
import awais.instagrabber.fragments.main.ProfileFragment
import awais.instagrabber.fragments.settings.PreferenceKeys import awais.instagrabber.fragments.settings.PreferenceKeys
import awais.instagrabber.interfaces.SwipeEvent import awais.instagrabber.interfaces.SwipeEvent
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
@ -38,14 +41,13 @@ import awais.instagrabber.models.enums.StoryPaginationType
import awais.instagrabber.repositories.requests.StoryViewerOptions import awais.instagrabber.repositories.requests.StoryViewerOptions
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
import awais.instagrabber.repositories.responses.stories.* import awais.instagrabber.repositories.responses.stories.*
import awais.instagrabber.utils.* import awais.instagrabber.utils.Constants
import awais.instagrabber.utils.DownloadUtils.download import awais.instagrabber.utils.DownloadUtils.download
import awais.instagrabber.utils.TextUtils.epochSecondToString import awais.instagrabber.utils.TextUtils.epochSecondToString
import awais.instagrabber.utils.ResponseBodyUtils
import awais.instagrabber.utils.Utils
import awais.instagrabber.utils.extensions.TAG import awais.instagrabber.utils.extensions.TAG
import awais.instagrabber.viewmodels.ArchivesViewModel import awais.instagrabber.viewmodels.*
import awais.instagrabber.viewmodels.FeedStoriesViewModel
import awais.instagrabber.viewmodels.HighlightsViewModel
import awais.instagrabber.viewmodels.StoryFragmentViewModel
import awais.instagrabber.webservices.MediaRepository import awais.instagrabber.webservices.MediaRepository
import awais.instagrabber.webservices.StoriesRepository import awais.instagrabber.webservices.StoriesRepository
import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.drawee.backends.pipeline.Fresco
@ -68,10 +70,8 @@ import java.util.*
class StoryViewerFragment : Fragment() { class StoryViewerFragment : Fragment() {
private val TAG = "StoryViewerFragment" private val TAG = "StoryViewerFragment"
private val cookie = Utils.settingsHelper.getString(Constants.COOKIE)
private var root: View? = null private var root: View? = null
private var currentStoryUsername: String? = null private var currentStoryUsername: String? = null
private var highlightTitle: String? = null
private var storiesAdapter: StoriesAdapter? = null private var storiesAdapter: StoriesAdapter? = null
private var swipeEvent: SwipeEvent? = null private var swipeEvent: SwipeEvent? = null
private var gestureDetector: GestureDetectorCompat? = null private var gestureDetector: GestureDetectorCompat? = null
@ -84,10 +84,7 @@ class StoryViewerFragment : Fragment() {
private var actionBarTitle: String? = null private var actionBarTitle: String? = null
private var actionBarSubtitle: String? = null private var actionBarSubtitle: String? = null
private var fetching = false
private val sticking = false
private var shouldRefresh = true private var shouldRefresh = true
private var dmVisible = false
private var currentFeedStoryIndex = 0 private var currentFeedStoryIndex = 0
private var sliderValue = 0.0 private var sliderValue = 0.0
private var options: StoryViewerOptions? = null private var options: StoryViewerOptions? = null
@ -95,6 +92,7 @@ class StoryViewerFragment : Fragment() {
private var backStackSavedStateResultLiveData: MutableLiveData<Any?>? = null private var backStackSavedStateResultLiveData: MutableLiveData<Any?>? = null
private lateinit var fragmentActivity: AppCompatActivity private lateinit var fragmentActivity: AppCompatActivity
private lateinit var storiesViewModel: StoryFragmentViewModel private lateinit var storiesViewModel: StoryFragmentViewModel
private lateinit var appStateViewModel: AppStateViewModel
private lateinit var binding: FragmentStoryViewerBinding private lateinit var binding: FragmentStoryViewerBinding
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@ -123,6 +121,7 @@ class StoryViewerFragment : Fragment() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
fragmentActivity = requireActivity() as AppCompatActivity fragmentActivity = requireActivity() as AppCompatActivity
storiesViewModel = ViewModelProvider(this).get(StoryFragmentViewModel::class.java) storiesViewModel = ViewModelProvider(this).get(StoryFragmentViewModel::class.java)
appStateViewModel = ViewModelProvider(fragmentActivity).get(AppStateViewModel::class.java)
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
@ -152,12 +151,7 @@ class StoryViewerFragment : Fragment() {
menuProfile!!.isVisible = profileVisible menuProfile!!.isVisible = profileVisible
} }
override fun onPrepareOptionsMenu(menu: Menu) {
// hide menu items from activity
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
val context = context ?: return false
val itemId = item.itemId val itemId = item.itemId
if (itemId == R.id.action_profile) { if (itemId == R.id.action_profile) {
val username = storiesViewModel.getCurrentStory().value?.user?.username val username = storiesViewModel.getCurrentStory().value?.user?.username
@ -205,18 +199,18 @@ class StoryViewerFragment : Fragment() {
val type = options!!.type val type = options!!.type
if (currentFeedStoryIndex >= 0) { if (currentFeedStoryIndex >= 0) {
listViewModel = when (type) { listViewModel = when (type) {
StoryViewerOptions.Type.HIGHLIGHT -> ViewModelProvider(fragmentActivity).get( StoryViewerOptions.Type.HIGHLIGHT -> {
HighlightsViewModel::class.java val pArgs = Bundle()
) pArgs.putString("username", options!!.name)
StoryViewerOptions.Type.STORY_ARCHIVE -> ViewModelProvider(fragmentActivity).get( ViewModelProvider(
ArchivesViewModel::class.java this, ProfileFragmentViewModelFactory(null, null, this, pArgs)
) ).get(ProfileFragmentViewModel::class.java)
StoryViewerOptions.Type.FEED_STORY_POSITION -> ViewModelProvider(fragmentActivity).get( }
FeedStoriesViewModel::class.java StoryViewerOptions.Type.STORY_ARCHIVE ->
) ViewModelProvider(fragmentActivity).get(ArchivesViewModel::class.java)
else -> ViewModelProvider(fragmentActivity).get( StoryViewerOptions.Type.FEED_STORY_POSITION ->
FeedStoriesViewModel::class.java ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel::class.java)
) else -> ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel::class.java)
} }
} }
setupButtons() setupButtons()
@ -228,7 +222,7 @@ class StoryViewerFragment : Fragment() {
val context = context ?: return val context = context ?: return
binding.storiesList.layoutManager = binding.storiesList.layoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
storiesAdapter = StoriesAdapter { model: StoryMedia?, position: Int -> storiesAdapter = StoriesAdapter { _, position ->
storiesViewModel.setMedia(position) storiesViewModel.setMedia(position)
} }
binding.storiesList.adapter = storiesAdapter binding.storiesList.adapter = storiesAdapter
@ -240,15 +234,13 @@ class StoryViewerFragment : Fragment() {
storyMedias.set(0, newItem) storyMedias.set(0, newItem)
storiesAdapter!!.submitList(storyMedias) storiesAdapter!!.submitList(storyMedias)
storiesViewModel.setMedia(0) storiesViewModel.setMedia(0)
binding.listToggle.setEnabled(true) binding.listToggle.isEnabled = true
binding.storiesList.setVisibility( binding.storiesList.visibility = if (Utils.settingsHelper.getBoolean(PreferenceKeys.PREF_STORY_SHOW_LIST)) View.VISIBLE
if (Utils.settingsHelper.getBoolean(PreferenceKeys.PREF_STORY_SHOW_LIST)) View.VISIBLE else View.GONE
else View.GONE
)
} }
else { else {
binding.listToggle.setEnabled(false) binding.listToggle.isEnabled = false
binding.storiesList.setVisibility(View.GONE) binding.storiesList.visibility = View.GONE
} }
}) })
storiesViewModel.getDate().observe(fragmentActivity, { storiesViewModel.getDate().observe(fragmentActivity, {
@ -266,8 +258,6 @@ class StoryViewerFragment : Fragment() {
storiesViewModel.getOptions().observe(fragmentActivity, { storiesViewModel.getOptions().observe(fragmentActivity, {
binding.stickers.isEnabled = it.first.size > 0 binding.stickers.isEnabled = it.first.size > 0
}) })
resetView()
} }
private fun setupButtons() { private fun setupButtons() {
@ -278,72 +268,78 @@ class StoryViewerFragment : Fragment() {
binding.btnReply.setOnClickListener({ _ -> createReplyDialog(null) }) binding.btnReply.setOnClickListener({ _ -> createReplyDialog(null) })
binding.stickers.setOnClickListener({ _ -> showStickerMenu() }) binding.stickers.setOnClickListener({ _ -> showStickerMenu() })
binding.listToggle.setOnClickListener({ _ -> binding.listToggle.setOnClickListener({ _ ->
binding.storiesList.setVisibility( binding.storiesList.visibility = if (binding.storiesList.visibility == View.GONE) View.VISIBLE
if (binding.storiesList.visibility == View.GONE) View.VISIBLE else View.GONE
else View.GONE
)
}) })
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
private fun setupListeners() { private fun setupListeners() {
val hasFeedStories: Boolean var liveModels: LiveData<List<Story>?>? = null
var models: List<Story>? = null
if (currentFeedStoryIndex >= 0) { if (currentFeedStoryIndex >= 0) {
val type = options!!.type val type = options!!.type
when (type) { when (type) {
StoryViewerOptions.Type.HIGHLIGHT -> { StoryViewerOptions.Type.HIGHLIGHT -> {
val highlightsViewModel = listViewModel as HighlightsViewModel? val profileFragmentViewModel = listViewModel as ProfileFragmentViewModel?
models = highlightsViewModel!!.list.value appStateViewModel.currentUserLiveData.observe(
viewLifecycleOwner, profileFragmentViewModel!!::setCurrentUser
)
profileFragmentViewModel.currentUserProfileActionLiveData.observe(viewLifecycleOwner) {}
profileFragmentViewModel.userHighlights.observe(viewLifecycleOwner) {}
liveModels = profileFragmentViewModel.highlights
} }
StoryViewerOptions.Type.FEED_STORY_POSITION -> { StoryViewerOptions.Type.FEED_STORY_POSITION -> {
val feedStoriesViewModel = listViewModel as FeedStoriesViewModel? val feedStoriesViewModel = listViewModel as FeedStoriesViewModel?
models = feedStoriesViewModel!!.list.value liveModels = feedStoriesViewModel!!.list
} }
StoryViewerOptions.Type.STORY_ARCHIVE -> { StoryViewerOptions.Type.STORY_ARCHIVE -> {
val archivesViewModel = listViewModel as ArchivesViewModel? val archivesViewModel = listViewModel as ArchivesViewModel?
models = archivesViewModel!!.list.value liveModels = archivesViewModel!!.list
} }
} }
} }
hasFeedStories = models != null && !models.isEmpty() if (liveModels != null) liveModels.observe(viewLifecycleOwner, { models ->
Log.d("austin_debug", "models (observer): " + models)
storiesViewModel.getPagination().observe(fragmentActivity, { storiesViewModel.getPagination().observe(fragmentActivity, {
if (models != null) { if (models != null) {
when (it) { when (it) {
StoryPaginationType.FORWARD -> { StoryPaginationType.FORWARD -> {
if (currentFeedStoryIndex == models.size - 1) if (currentFeedStoryIndex == models.size - 1)
Toast.makeText(
context,
R.string.no_more_stories,
Toast.LENGTH_SHORT
).show()
else paginateStories(false, currentFeedStoryIndex == models.size - 2)
}
StoryPaginationType.BACKWARD -> {
if (currentFeedStoryIndex == 0)
Toast.makeText(
context,
R.string.no_more_stories,
Toast.LENGTH_SHORT
).show()
else paginateStories(true, false)
}
StoryPaginationType.ERROR -> {
Toast.makeText( Toast.makeText(
context, context,
R.string.no_more_stories, R.string.downloader_unknown_error,
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
else paginateStories(false, currentFeedStoryIndex == models.size - 2) }
} }
StoryPaginationType.BACKWARD -> {
if (currentFeedStoryIndex == 0)
Toast.makeText(
context,
R.string.no_more_stories,
Toast.LENGTH_SHORT
).show()
else paginateStories(true, false)
}
StoryPaginationType.ERROR -> {
Toast.makeText(
context,
R.string.downloader_unknown_error,
Toast.LENGTH_SHORT
).show()
}
StoryPaginationType.DO_NOTHING -> {
} // do nothing
} }
})
if (models != null && !models.isEmpty()) {
binding.btnBackward.isEnabled = currentFeedStoryIndex != 0
binding.btnForward.isEnabled = currentFeedStoryIndex != models.size - 1
resetView()
} }
}) })
val context = context ?: return val context = context ?: return
swipeEvent = label@ SwipeEvent { isRightSwipe: Boolean -> swipeEvent = SwipeEvent { isRightSwipe: Boolean ->
storiesViewModel.paginate(isRightSwipe) storiesViewModel.paginate(isRightSwipe)
} }
gestureDetector = GestureDetectorCompat(context, SwipeGestureListener(swipeEvent)) gestureDetector = GestureDetectorCompat(context, SwipeGestureListener(swipeEvent))
@ -370,13 +366,7 @@ class StoryViewerFragment : Fragment() {
return false return false
} }
} }
if (hasFeedStories) {
binding.btnBackward.isEnabled = currentFeedStoryIndex != 0
binding.btnForward.isEnabled = currentFeedStoryIndex != models!!.size - 1
}
binding.imageViewer.setTapListener(simpleOnGestureListener) binding.imageViewer.setTapListener(simpleOnGestureListener)
// process stickers
} }
private fun resetView() { private fun resetView() {
@ -389,15 +379,14 @@ class StoryViewerFragment : Fragment() {
var fetchOptions: StoryViewerOptions? = null var fetchOptions: StoryViewerOptions? = null
when (type) { when (type) {
StoryViewerOptions.Type.HIGHLIGHT -> { StoryViewerOptions.Type.HIGHLIGHT -> {
val highlightsViewModel = listViewModel as HighlightsViewModel? val profileFragmentViewModel = listViewModel as ProfileFragmentViewModel?
val models = highlightsViewModel!!.list.value val models = profileFragmentViewModel!!.highlights.value
Log.d("austin_debug", "models (resetView): " + models)
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) Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show()
.show()
return return
} }
val (id, _, _, _, _, _, _, _, _, title) = models[currentFeedStoryIndex] fetchOptions = StoryViewerOptions.forHighlight(models[currentFeedStoryIndex].id)
fetchOptions = StoryViewerOptions.forHighlight(id)
} }
StoryViewerOptions.Type.FEED_STORY_POSITION -> { StoryViewerOptions.Type.FEED_STORY_POSITION -> {
val feedStoriesViewModel = listViewModel as FeedStoriesViewModel? val feedStoriesViewModel = listViewModel as FeedStoriesViewModel?
@ -434,7 +423,9 @@ class StoryViewerFragment : Fragment() {
return return
} }
storiesViewModel.fetchStory(fetchOptions).observe(fragmentActivity, { storiesViewModel.fetchStory(fetchOptions).observe(fragmentActivity, {
// toast error if necessary? if (it.status == Resource.Status.ERROR) {
Toast.makeText(context, "Error: " + it.message, Toast.LENGTH_SHORT).show()
}
}) })
} }
@ -578,7 +569,7 @@ class StoryViewerFragment : Fragment() {
}) })
player!!.setMediaSource(mediaSource) player!!.setMediaSource(mediaSource)
player!!.prepare() player!!.prepare()
binding.playerView.setOnClickListener { v: View? -> binding.playerView.setOnClickListener { _ ->
if (player != null) { if (player != null) {
if (player!!.playbackState == Player.STATE_ENDED) player!!.seekTo(0) if (player!!.playbackState == Player.STATE_ENDED) player!!.seekTo(0)
player!!.playWhenReady = player!!.playWhenReady =

View File

@ -843,7 +843,7 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
private fun setupHighlights() { private fun setupHighlights() {
val context = context ?: return val context = context ?: return
highlightsAdapter = HighlightsAdapter { model, position -> highlightsAdapter = HighlightsAdapter { model, position ->
val options = StoryViewerOptions.forHighlight(model.title) val options = StoryViewerOptions.forHighlight(model.user?.username)
options.currentFeedStoryIndex = position options.currentFeedStoryIndex = position
val action = ProfileFragmentDirections.actionProfileFragmentToStoryViewerFragment(options) val action = ProfileFragmentDirections.actionProfileFragmentToStoryViewerFragment(options)
NavHostFragment.findNavController(this).navigate(action) NavHostFragment.findNavController(this).navigate(action)

View File

@ -1,19 +0,0 @@
package awais.instagrabber.viewmodels;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import java.util.List;
import awais.instagrabber.repositories.responses.stories.Story;
public class HighlightsViewModel extends ViewModel {
private MutableLiveData<List<Story>> list;
public MutableLiveData<List<Story>> getList() {
if (list == null) {
list = new MutableLiveData<>();
}
return list;
}
}

View File

@ -218,6 +218,7 @@ class ProfileFragmentViewModel(
} }
} }
} }
val highlights: LiveData<List<Story>?> = userHighlights.map { it.data }
private suspend fun fetchUser( private suspend fun fetchUser(
currentUser: User?, currentUser: User?,
@ -326,7 +327,7 @@ class ProfileFragmentViewModel(
val currentUserId = currentUser.value?.data?.pk ?: return@afterPrevious val currentUserId = currentUser.value?.data?.pk ?: return@afterPrevious
val targetUserId = profile.value?.data?.pk ?: return@afterPrevious val targetUserId = profile.value?.data?.pk ?: return@afterPrevious
val csrfToken = csrfToken ?: return@afterPrevious val csrfToken = csrfToken ?: return@afterPrevious
val deviceUuid = deviceUuid ?: return@afterPrevious val deviceUuid = deviceUuid
if (following) { if (following) {
if (!confirmed) { if (!confirmed) {
_eventLiveData.postValue(Event(ShowConfirmUnfollowDialog)) _eventLiveData.postValue(Event(ShowConfirmUnfollowDialog))
@ -365,7 +366,7 @@ class ProfileFragmentViewModel(
val currentUserId = currentUser.value?.data?.pk ?: return@afterPrevious val currentUserId = currentUser.value?.data?.pk ?: return@afterPrevious
val targetUserId = profile.value?.data?.pk ?: return@afterPrevious val targetUserId = profile.value?.data?.pk ?: return@afterPrevious
val csrfToken = csrfToken ?: return@afterPrevious val csrfToken = csrfToken ?: return@afterPrevious
val deviceUuid = deviceUuid ?: return@afterPrevious val deviceUuid = deviceUuid
val username = profile.value?.data?.username ?: return@afterPrevious val username = profile.value?.data?.username ?: return@afterPrevious
val thread = directMessagesRepository.createThread( val thread = directMessagesRepository.createThread(
csrfToken, csrfToken,
@ -399,7 +400,7 @@ class ProfileFragmentViewModel(
val profile = profile.value?.data ?: return@afterPrevious val profile = profile.value?.data ?: return@afterPrevious
friendshipRepository.toggleRestrict( friendshipRepository.toggleRestrict(
csrfToken ?: return@afterPrevious, csrfToken ?: return@afterPrevious,
deviceUuid ?: return@afterPrevious, deviceUuid,
profile.pk, profile.pk,
!(profile.friendshipStatus?.isRestricted ?: false), !(profile.friendshipStatus?.isRestricted ?: false),
) )
@ -421,7 +422,7 @@ class ProfileFragmentViewModel(
friendshipRepository.changeBlock( friendshipRepository.changeBlock(
csrfToken ?: return@afterPrevious, csrfToken ?: return@afterPrevious,
currentUser.value?.data?.pk ?: return@afterPrevious, currentUser.value?.data?.pk ?: return@afterPrevious,
deviceUuid ?: return@afterPrevious, deviceUuid,
profile.friendshipStatus?.blocking ?: return@afterPrevious, profile.friendshipStatus?.blocking ?: return@afterPrevious,
profile.pk profile.pk
) )
@ -443,7 +444,7 @@ class ProfileFragmentViewModel(
friendshipRepository.changeMute( friendshipRepository.changeMute(
csrfToken ?: return@afterPrevious, csrfToken ?: return@afterPrevious,
currentUser.value?.data?.pk ?: return@afterPrevious, currentUser.value?.data?.pk ?: return@afterPrevious,
deviceUuid ?: return@afterPrevious, deviceUuid,
profile.friendshipStatus?.isMutingReel ?: return@afterPrevious, profile.friendshipStatus?.isMutingReel ?: return@afterPrevious,
profile.pk, profile.pk,
true true
@ -466,7 +467,7 @@ class ProfileFragmentViewModel(
friendshipRepository.changeMute( friendshipRepository.changeMute(
csrfToken ?: return@afterPrevious, csrfToken ?: return@afterPrevious,
currentUser.value?.data?.pk ?: return@afterPrevious, currentUser.value?.data?.pk ?: return@afterPrevious,
deviceUuid ?: return@afterPrevious, deviceUuid,
profile.friendshipStatus?.muting ?: return@afterPrevious, profile.friendshipStatus?.muting ?: return@afterPrevious,
profile.pk, profile.pk,
false false
@ -488,7 +489,7 @@ class ProfileFragmentViewModel(
friendshipRepository.removeFollower( friendshipRepository.removeFollower(
csrfToken ?: return@afterPrevious, csrfToken ?: return@afterPrevious,
currentUser.value?.data?.pk ?: return@afterPrevious, currentUser.value?.data?.pk ?: return@afterPrevious,
deviceUuid ?: return@afterPrevious, deviceUuid,
profile.value?.data?.pk ?: return@afterPrevious profile.value?.data?.pk ?: return@afterPrevious
) )
profileAction.postValue(REFRESH_FRIENDSHIP) profileAction.postValue(REFRESH_FRIENDSHIP)