Stories: Pass recipients through via constructor.

fork-5.53.8
Alex Hart 2022-04-20 14:33:43 -03:00
rodzic dfcadde076
commit 8b1552952c
9 zmienionych plików z 86 dodań i 17 usunięć

Wyświetl plik

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

Wyświetl plik

@ -1244,7 +1244,7 @@ public class ConversationParentFragment extends Fragment
} }
private void handleStoryRingClick() { 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() { private void handleConversationSettings() {

Wyświetl plik

@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.thoughtcrime.securesms.verify.VerifyIdentityActivity; import org.thoughtcrime.securesms.verify.VerifyIdentityActivity;
import java.util.Collections;
import java.util.Objects; import java.util.Objects;
import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.CompositeDisposable;
@ -140,7 +141,7 @@ final class RecipientDialogViewModel extends ViewModel {
if (storyViewState.getValue() == null || storyViewState.getValue() == StoryViewState.NONE) { if (storyViewState.getValue() == null || storyViewState.getValue() == StoryViewState.NONE) {
onMessageClicked(activity); onMessageClicked(activity);
} else { } 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) { if (storyViewState.getValue() == null || storyViewState.getValue() == StoryViewState.NONE) {
activity.startActivity(ConversationSettingsActivity.forRecipient(activity, recipientDialogRepository.getRecipientId())); activity.startActivity(ConversationSettingsActivity.forRecipient(activity, recipientDialogRepository.getRecipientId()));
} else { } 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()));
} }
} }

Wyświetl plik

@ -206,7 +206,19 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
null to record.slideDeck.thumbnailSlide?.uri 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 = { onForwardStory = {

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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