Fix story viewed state retention.

main
Alex Hart 2022-10-28 16:51:13 -03:00
rodzic 4e3bfadfbe
commit 5d4d6db197
5 zmienionych plików z 96 dodań i 3 usunięć

Wyświetl plik

@ -17,6 +17,8 @@ import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaControllerOwner
import org.thoughtcrime.securesms.stories.StoryViewerArgs
import org.thoughtcrime.securesms.stories.viewer.page.StoryViewStateCache
import org.thoughtcrime.securesms.stories.viewer.page.StoryViewStateViewModel
import org.thoughtcrime.securesms.util.FullscreenHelper
import org.thoughtcrime.securesms.util.ServiceUtil
import org.thoughtcrime.securesms.util.ViewUtil
@ -26,6 +28,7 @@ import kotlin.math.min
class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControllerOwner {
private val viewModel: StoryVolumeViewModel by viewModels()
private val storyViewStateViewModel: StoryViewStateViewModel by viewModels()
override lateinit var voiceNoteMediaController: VoiceNoteMediaController
@ -35,6 +38,13 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
}
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
if (savedInstanceState != null) {
val cache: StoryViewStateCache? = savedInstanceState.getParcelable(DATA_CACHE)
if (cache != null) {
storyViewStateViewModel.storyViewStateCache.putAll(cache)
}
}
StoryMutePolicy.initialize()
Glide.get(this).setMemoryCategory(MemoryCategory.HIGH)
FullscreenHelper.showSystemUI(window)
@ -59,6 +69,11 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(DATA_CACHE, storyViewStateViewModel.storyViewStateCache)
}
override fun onDestroy() {
super.onDestroy()
Glide.get(this).setMemoryCategory(MemoryCategory.NORMAL)
@ -115,6 +130,7 @@ class StoryViewerActivity : PassphraseRequiredActivity(), VoiceNoteMediaControll
companion object {
private const val ARGS = "story.viewer.args"
private const val DATA_CACHE = "story.viewer.cache"
@JvmStatic
fun createIntent(

Wyświetl plik

@ -0,0 +1,67 @@
package org.thoughtcrime.securesms.stories.viewer.page
import android.os.Parcel
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.thoughtcrime.securesms.util.ParcelUtil
/**
* Activity-bounds ViewModel which tracks the viewed state for stories.
*/
class StoryViewStateCache() : Parcelable {
private val viewStateMap: MutableMap<Long, Boolean> = mutableMapOf()
constructor(parcel: Parcel) : this() {
synchronized(this) {
val entries: Collection<Entry> = ParcelUtil.readParcelableCollection(parcel, Entry::class.java)
entries.forEach {
viewStateMap[it.storyId] = it.hasSelfViewed
}
}
}
fun putAll(cache: StoryViewStateCache) {
synchronized(this) {
viewStateMap.putAll(cache.viewStateMap)
}
}
/**
* If storyId is in our map, return its value. Otherwise, insert and return the given state.
*/
fun getOrPut(storyId: Long, hasSelfViewed: Boolean): Boolean {
synchronized(this) {
return if (viewStateMap.containsKey(storyId)) {
viewStateMap[storyId]!!
} else {
viewStateMap[storyId] = hasSelfViewed
hasSelfViewed
}
}
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
ParcelUtil.writeParcelableCollection(parcel, viewStateMap.map { Entry(it.key, it.value) })
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<StoryViewStateCache> {
override fun createFromParcel(parcel: Parcel): StoryViewStateCache {
return StoryViewStateCache(parcel)
}
override fun newArray(size: Int): Array<StoryViewStateCache?> {
return arrayOfNulls(size)
}
}
@Parcelize
data class Entry(
val storyId: Long,
val hasSelfViewed: Boolean
) : Parcelable
}

Wyświetl plik

@ -0,0 +1,7 @@
package org.thoughtcrime.securesms.stories.viewer.page
import androidx.lifecycle.ViewModel
class StoryViewStateViewModel : ViewModel() {
val storyViewStateCache = StoryViewStateCache()
}

Wyświetl plik

@ -115,12 +115,15 @@ class StoryViewerPageFragment :
private var volumeOutAnimator: Animator? = null
private var volumeDebouncer: Debouncer = Debouncer(3, TimeUnit.SECONDS)
private val storyViewStateViewModel: StoryViewStateViewModel by viewModels()
private val viewModel: StoryViewerPageViewModel by viewModels(
factoryProducer = {
StoryViewerPageViewModel.Factory(
storyViewerPageArgs,
StoryViewerPageRepository(
requireContext()
requireContext(),
storyViewStateViewModel.storyViewStateCache
),
StoryCache(
GlideApp.with(requireActivity()),

Wyświetl plik

@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.util.Base64
/**
* Open for testing.
*/
open class StoryViewerPageRepository(context: Context) {
open class StoryViewerPageRepository(context: Context, private val storyViewStateCache: StoryViewStateCache) {
companion object {
private val TAG = Log.tag(StoryViewerPageRepository::class.java)
@ -88,7 +88,7 @@ open class StoryViewerPageRepository(context: Context) {
content = getContent(record as MmsMessageRecord),
conversationMessage = ConversationMessage.ConversationMessageFactory.createWithUnresolvedData(context, record),
allowsReplies = record.storyType.isStoryWithReplies,
hasSelfViewed = if (record.isOutgoing) true else record.viewedReceiptCount > 0
hasSelfViewed = storyViewStateCache.getOrPut(record.id, if (record.isOutgoing) true else record.viewedReceiptCount > 0)
)
emitter.onNext(story)