kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fix story viewed state retention.
rodzic
4e3bfadfbe
commit
5d4d6db197
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package org.thoughtcrime.securesms.stories.viewer.page
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class StoryViewStateViewModel : ViewModel() {
|
||||
val storyViewStateCache = StoryViewStateCache()
|
||||
}
|
|
@ -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()),
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue