diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt index ae96f5064d..ea1400889b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/StoryViewerViewModel.kt @@ -9,7 +9,9 @@ import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable +import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.kotlin.plusAssign +import io.reactivex.rxjava3.kotlin.subscribeBy import io.reactivex.rxjava3.subjects.BehaviorSubject import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.recipients.RecipientId @@ -17,7 +19,10 @@ import org.thoughtcrime.securesms.stories.Stories import org.thoughtcrime.securesms.stories.StoryViewerArgs import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.rx.RxStore +import java.util.concurrent.TimeUnit import kotlin.math.max +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds class StoryViewerViewModel( private val storyViewerArgs: StoryViewerArgs, @@ -62,6 +67,25 @@ class StoryViewerViewModel( val isChildScrolling: Observable = childScrollStatePublisher.distinctUntilChanged() val isFirstTimeNavigationShowing: Observable = firstTimeNavigationPublisher.distinctUntilChanged() + /** + * Post an action *after* the story load state is ready. + * A slight delay is applied here to ensure that animations settle + * before the action takes place. Otherwise, some strange windowing + * problems can occur. + */ + fun postAfterLoadStateReady( + delay: Duration = 100.milliseconds, + action: () -> Unit + ): Disposable { + return loadState + .filter { it.isReady() } + .delay(delay.inWholeMilliseconds, TimeUnit.MILLISECONDS) + .firstOrError() + .ignoreElement() + .observeOn(AndroidSchedulers.mainThread()) + .subscribeBy { action() } + } + fun addHiddenAndRefresh(hidden: Set) { this.hidden.addAll(hidden) refresh() diff --git a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageFragment.kt index 0dd1df7509..29b186e384 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/stories/viewer/page/StoryViewerPageFragment.kt @@ -451,7 +451,10 @@ class StoryViewerPageFragment : if (storyViewerPageArgs.source == StoryViewerPageArgs.Source.NOTIFICATION) { startReply(isFromNotification = true, groupReplyStartPosition = storyViewerPageArgs.groupReplyStartPosition) } else if (storyViewerPageArgs.source == StoryViewerPageArgs.Source.INFO_CONTEXT && state.selectedPostIndex in state.posts.indices) { - showInfo(state.posts[state.selectedPostIndex]) + viewModel.setIsDisplayingInfoDialog(true) + lifecycleDisposable += sharedViewModel.postAfterLoadStateReady { + showInfo(state.posts[state.selectedPostIndex]) + } } } }