Stories: Pass recipients through via constructor.

This commit is contained in:
Alex Hart 2022-04-20 14:33:43 -03:00
parent dfcadde076
commit 8b1552952c
9 changed files with 86 additions and 17 deletions

View file

@ -1616,7 +1616,8 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
Recipient.resolved(messageRecord.getQuote().getAuthor()).shouldHideStory(),
null,
null,
null
null,
Collections.emptyList()
));
return;

View file

@ -1244,7 +1244,7 @@ public class ConversationParentFragment extends Fragment
}
private void handleStoryRingClick() {
startActivity(StoryViewerActivity.createIntent(requireContext(), recipient.getId(), -1L, recipient.get().shouldHideStory(), null, null, null));
startActivity(StoryViewerActivity.createIntent(requireContext(), recipient.getId(), -1L, recipient.get().shouldHideStory(), null, null, null, Collections.emptyList()));
}
private void handleConversationSettings() {

View file

@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.thoughtcrime.securesms.verify.VerifyIdentityActivity;
import java.util.Collections;
import java.util.Objects;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
@ -140,7 +141,7 @@ final class RecipientDialogViewModel extends ViewModel {
if (storyViewState.getValue() == null || storyViewState.getValue() == StoryViewState.NONE) {
onMessageClicked(activity);
} else {
activity.startActivity(StoryViewerActivity.createIntent(activity, recipientDialogRepository.getRecipientId(), -1L, recipient.getValue().shouldHideStory(), null, null, null));
activity.startActivity(StoryViewerActivity.createIntent(activity, recipientDialogRepository.getRecipientId(), -1L, recipient.getValue().shouldHideStory(), null, null, null, Collections.emptyList()));
}
}
@ -176,7 +177,7 @@ final class RecipientDialogViewModel extends ViewModel {
if (storyViewState.getValue() == null || storyViewState.getValue() == StoryViewState.NONE) {
activity.startActivity(ConversationSettingsActivity.forRecipient(activity, recipientDialogRepository.getRecipientId()));
} else {
activity.startActivity(StoryViewerActivity.createIntent(activity, recipientDialogRepository.getRecipientId(), -1L, recipient.getValue().shouldHideStory(), null, null, null));
activity.startActivity(StoryViewerActivity.createIntent(activity, recipientDialogRepository.getRecipientId(), -1L, recipient.getValue().shouldHideStory(), null, null, null, Collections.emptyList()));
}
}

View file

@ -206,7 +206,19 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
null to record.slideDeck.thumbnailSlide?.uri
}
startActivityIfAble(StoryViewerActivity.createIntent(requireContext(), model.data.storyRecipient.id, -1L, model.data.isHidden, text, image, blur), options.toBundle())
startActivityIfAble(
StoryViewerActivity.createIntent(
context = requireContext(),
recipientId = model.data.storyRecipient.id,
storyId = -1L,
onlyIncludeHiddenStories = model.data.isHidden,
storyThumbTextModel = text,
storyThumbUri = image,
storyThumbBlur = blur,
recipientIds = viewModel.getRecipientIds(model.data.isHidden)
),
options.toBundle()
)
}
},
onForwardStory = {

View file

@ -8,6 +8,7 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.livedata.Store
class StoriesLandingViewModel(private val storiesLandingRepository: StoriesLandingRepository) : ViewModel() {
@ -45,6 +46,10 @@ class StoriesLandingViewModel(private val storiesLandingRepository: StoriesLandi
store.update { it.copy(isHiddenContentVisible = isExpanded) }
}
fun getRecipientIds(hidden: Boolean): List<RecipientId> {
return store.state.storiesLandingItems.filter { it.isHidden == hidden }.map { it.storyRecipient.id }
}
class Factory(private val storiesLandingRepository: StoriesLandingRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return modelClass.cast(StoriesLandingViewModel(storiesLandingRepository)) as T

View file

@ -41,7 +41,8 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
intent.getBooleanExtra(ARG_HIDDEN_STORIES, false),
intent.getParcelableExtra(ARG_CROSSFADE_TEXT_MODEL),
intent.getParcelableExtra(ARG_CROSSFADE_IMAGE_URI),
intent.getStringExtra(ARG_CROSSFADE_IMAGE_BLUR)
intent.getStringExtra(ARG_CROSSFADE_IMAGE_BLUR),
intent.getParcelableArrayListExtra(ARG_RECIPIENT_IDS)!!
)
)
.commit()
@ -61,6 +62,7 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
private const val ARG_CROSSFADE_TEXT_MODEL = "crossfade.text.model"
private const val ARG_CROSSFADE_IMAGE_URI = "crossfade.image.uri"
private const val ARG_CROSSFADE_IMAGE_BLUR = "crossfade.image.blur"
private const val ARG_RECIPIENT_IDS = "recipient_ids"
@JvmStatic
fun createIntent(
@ -70,7 +72,8 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
onlyIncludeHiddenStories: Boolean = false,
storyThumbTextModel: StoryTextPostModel? = null,
storyThumbUri: Uri? = null,
storyThumbBlur: BlurHash? = null
storyThumbBlur: BlurHash? = null,
recipientIds: List<RecipientId> = emptyList()
): Intent {
return Intent(context, StoryViewerActivity::class.java)
.putExtra(ARG_START_RECIPIENT_ID, recipientId)
@ -79,6 +82,7 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
.putExtra(ARG_CROSSFADE_TEXT_MODEL, storyThumbTextModel)
.putExtra(ARG_CROSSFADE_IMAGE_URI, storyThumbUri)
.putExtra(ARG_CROSSFADE_IMAGE_BLUR, storyThumbBlur?.hash)
.putParcelableArrayListExtra(ARG_RECIPIENT_IDS, ArrayList(recipientIds))
}
}
}

View file

@ -24,7 +24,7 @@ class StoryViewerFragment : Fragment(R.layout.stories_viewer_fragment), StoryVie
private val viewModel: StoryViewerViewModel by viewModels(
factoryProducer = {
StoryViewerViewModel.Factory(storyRecipientId, onlyIncludeHiddenStories, storyThumbTextModel, storyThumbUri, storuThumbBlur, StoryViewerRepository())
StoryViewerViewModel.Factory(storyRecipientId, onlyIncludeHiddenStories, storyThumbTextModel, storyThumbUri, storuThumbBlur, recipientIds, StoryViewerRepository())
}
)
@ -46,6 +46,9 @@ class StoryViewerFragment : Fragment(R.layout.stories_viewer_fragment), StoryVie
private val storuThumbBlur: BlurHash?
get() = requireArguments().getString(ARG_CROSSFADE_IMAGE_BLUR)?.let { BlurHash.parseOrNull(it) }
private val recipientIds: List<RecipientId>
get() = requireArguments().getParcelableArrayList(ARG_RECIPIENT_IDS)!!
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
storyPager = view.findViewById(R.id.story_item_pager)
@ -113,6 +116,7 @@ class StoryViewerFragment : Fragment(R.layout.stories_viewer_fragment), StoryVie
private const val ARG_CROSSFADE_TEXT_MODEL = "crossfade.text.model"
private const val ARG_CROSSFADE_IMAGE_URI = "crossfade.image.uri"
private const val ARG_CROSSFADE_IMAGE_BLUR = "crossfade.image.blur"
private const val ARG_RECIPIENT_IDS = "start.recipient.ids"
fun create(
storyRecipientId: RecipientId,
@ -120,7 +124,8 @@ class StoryViewerFragment : Fragment(R.layout.stories_viewer_fragment), StoryVie
onlyIncludeHiddenStories: Boolean,
storyThumbTextModel: StoryTextPostModel? = null,
storyThumbUri: Uri? = null,
storyThumbBlur: String? = null
storyThumbBlur: String? = null,
recipientIds: List<RecipientId> = emptyList()
): Fragment {
return StoryViewerFragment().apply {
arguments = Bundle().apply {
@ -130,6 +135,7 @@ class StoryViewerFragment : Fragment(R.layout.stories_viewer_fragment), StoryVie
putParcelable(ARG_CROSSFADE_TEXT_MODEL, storyThumbTextModel)
putParcelable(ARG_CROSSFADE_IMAGE_URI, storyThumbUri)
putString(ARG_CROSSFADE_IMAGE_BLUR, storyThumbBlur)
putParcelableArrayList(ARG_RECIPIENT_IDS, ArrayList(recipientIds))
}
}
}

View file

@ -6,6 +6,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import org.thoughtcrime.securesms.blurhash.BlurHash
@ -20,6 +21,7 @@ class StoryViewerViewModel(
storyThumbTextModel: StoryTextPostModel?,
storyThumbUri: Uri?,
storyThumbBlur: BlurHash?,
private val recipientIds: List<RecipientId>,
private val repository: StoryViewerRepository,
) : ViewModel() {
@ -64,9 +66,17 @@ class StoryViewerViewModel(
scrollStatePublisher.value = isScrolling
}
private fun getStories(): Single<List<RecipientId>> {
return if (recipientIds.isNotEmpty()) {
Single.just(recipientIds)
} else {
repository.getStories(onlyIncludeHiddenStories)
}
}
private fun refresh() {
disposables.clear()
disposables += repository.getStories(onlyIncludeHiddenStories).subscribe { recipientIds ->
disposables += getStories().subscribe { recipientIds ->
store.update {
val page: Int = if (it.pages.isNotEmpty()) {
val oldPage = it.page
@ -157,10 +167,21 @@ class StoryViewerViewModel(
private val storyThumbTextModel: StoryTextPostModel?,
private val storyThumbUri: Uri?,
private val storyThumbBlur: BlurHash?,
private val recipientIds: List<RecipientId>,
private val repository: StoryViewerRepository
) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return modelClass.cast(StoryViewerViewModel(startRecipientId, onlyIncludeHiddenStories, storyThumbTextModel, storyThumbUri, storyThumbBlur, repository)) as T
return modelClass.cast(
StoryViewerViewModel(
startRecipientId,
onlyIncludeHiddenStories,
storyThumbTextModel,
storyThumbUri,
storyThumbBlur,
recipientIds,
repository
)
) as T
}
}
}

View file

@ -10,6 +10,8 @@ import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.thoughtcrime.securesms.recipients.RecipientId
@ -28,6 +30,23 @@ class StoryViewerViewModelTest {
RxJavaPlugins.reset()
}
@Test
fun `Given a list of recipients, when I initialize, then I expect the list`() {
// GIVEN
val repoStories: List<RecipientId> = (1L..5L).map(RecipientId::from)
whenever(repository.getStories(any())).doReturn(Single.just(repoStories))
val injectedStories: List<RecipientId> = (6L..10L).map(RecipientId::from)
// WHEN
val testSubject = StoryViewerViewModel(injectedStories.first(), false, null, null, null, injectedStories, repository)
testScheduler.triggerActions()
// THEN
verify(repository, never()).getStories(any())
assertEquals(injectedStories, testSubject.stateSnapshot.pages)
}
@Test
fun `Given five stories, when I initialize with story 2, then I expect to be on the right page`() {
// GIVEN
@ -36,7 +55,7 @@ class StoryViewerViewModelTest {
whenever(repository.getStories(any())).doReturn(Single.just(stories))
// WHEN
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, repository)
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, emptyList(), repository)
testScheduler.triggerActions()
// THEN
@ -52,7 +71,7 @@ class StoryViewerViewModelTest {
val stories: List<RecipientId> = (1L..5L).map(RecipientId::from)
val startStory = RecipientId.from(1L)
whenever(repository.getStories(any())).doReturn(Single.just(stories))
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, repository)
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, emptyList(), repository)
testScheduler.triggerActions()
// WHEN
@ -72,7 +91,7 @@ class StoryViewerViewModelTest {
val stories: List<RecipientId> = (1L..5L).map(RecipientId::from)
val startStory = stories.last()
whenever(repository.getStories(any())).doReturn(Single.just(stories))
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, repository)
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, emptyList(), repository)
testScheduler.triggerActions()
// WHEN
@ -92,7 +111,7 @@ class StoryViewerViewModelTest {
val stories: List<RecipientId> = (1L..5L).map(RecipientId::from)
val startStory = stories.last()
whenever(repository.getStories(any())).doReturn(Single.just(stories))
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, repository)
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, emptyList(), repository)
testScheduler.triggerActions()
// WHEN
@ -112,7 +131,7 @@ class StoryViewerViewModelTest {
val stories: List<RecipientId> = (1L..5L).map(RecipientId::from)
val startStory = stories.first()
whenever(repository.getStories(any())).doReturn(Single.just(stories))
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, repository)
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, emptyList(), repository)
testScheduler.triggerActions()
// WHEN
@ -132,7 +151,7 @@ class StoryViewerViewModelTest {
val stories: List<RecipientId> = (1L..5L).map(RecipientId::from)
val startStory = stories.first()
whenever(repository.getStories(any())).doReturn(Single.just(stories))
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, repository)
val testSubject = StoryViewerViewModel(startStory, false, null, null, null, emptyList(), repository)
testScheduler.triggerActions()
// WHEN