mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-11 15:24:58 +00:00
android, desktop: open correct image in fullscreen viewer (#6869)
* android, desktop: open correct image in fullscreen viewer Fullscreen image viewer occasionally opened a different image than the one clicked. Root cause: when the LaunchedEffect probe at ImageFullScreenView.kt:48-55 calls getMedia(initialIndex - 1) to check whether a previous media item exists, getMedia returns null for both "no item" and "item found but failed to load" (e.g. undecodable bytes, missing file, crypto error). The probe treated null as "no previous item" and called scrollToStart(), which rewrote initialChatId to the chat's oldest media item - making the viewer display that oldest item instead of the clicked one. Fix: scrollToStart() no longer rewrites initialChatId. The pager is still repositioned to page 0; getMedia(0) resolves against the already-set initialChatId (the clicked item) and renders it correctly. * android, desktop: regression test for fullscreen viewer anchor preservation Drives the public providerForGallery interface: moves the anchor away from cItemId via currentPageChanged, calls scrollToStart, then reads the anchor back through onDismiss's scrollTo callback. The pre-fix code rewrote initialChatId to the chat's oldest showable, which would surface as scrollTo(2); the fix preserves the anchor and produces scrollTo(1). * plan: design doc for fullscreen viewer wrong-image fix Documents the pager state model, the root cause of the wrong-image bug, why the one-line deletion in scrollToStart fixes it for both call sites, and why the wider getMedia null-overload refactor is deliberately out of scope for this fix.
This commit is contained in:
-1
@@ -3597,7 +3597,6 @@ fun providerForGallery(
|
||||
|
||||
override fun scrollToStart() {
|
||||
initialIndex = 0
|
||||
initialChatId = chatItems.firstOrNull { canShowMedia(it) }?.id ?: return
|
||||
}
|
||||
|
||||
override fun onDismiss(index: Int) {
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package chat.simplex.app
|
||||
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.platform.chatModel
|
||||
import chat.simplex.common.views.chat.providerForGallery
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlin.test.AfterTest
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
// Regression for PR #6869: scrollToStart() must not rewrite initialChatId.
|
||||
class ProviderForGalleryTest {
|
||||
|
||||
// Synthetic items pass canShowMedia only when chatModel.connectedToRemote() is true.
|
||||
@BeforeTest
|
||||
fun connectChatModelToRemote() {
|
||||
chatModel.currentRemoteHost.value = RemoteHostInfo(
|
||||
remoteHostId = 0L,
|
||||
hostDeviceName = "",
|
||||
storePath = "",
|
||||
bindAddress_ = null,
|
||||
bindPort_ = null,
|
||||
sessionState = null,
|
||||
)
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
fun resetChatModel() {
|
||||
chatModel.currentRemoteHost.value = null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testScrollToStartPreservesAnchor() {
|
||||
val items = listOf(imageItem(1L), imageItem(2L), imageItem(3L))
|
||||
var scrolledTo: Int? = null
|
||||
val provider = providerForGallery(items, cItemId = 3L) { scrolledTo = it }
|
||||
|
||||
provider.currentPageChanged(provider.initialIndex - 1)
|
||||
provider.scrollToStart()
|
||||
provider.onDismiss(0)
|
||||
|
||||
assertEquals(1, scrolledTo)
|
||||
}
|
||||
|
||||
// Pins the onDismiss early-return contract that testScrollToStartPreservesAnchor
|
||||
// relies on to read the anchor back through the scrollTo callback.
|
||||
@Test
|
||||
fun testOnDismissOnActiveItemDoesNotScroll() {
|
||||
val items = listOf(imageItem(1L), imageItem(2L), imageItem(3L))
|
||||
var scrolledTo: Int? = null
|
||||
val provider = providerForGallery(items, cItemId = 3L) { scrolledTo = it }
|
||||
|
||||
provider.onDismiss(provider.initialIndex)
|
||||
|
||||
assertEquals(null, scrolledTo)
|
||||
}
|
||||
|
||||
private fun imageItem(id: Long): ChatItem =
|
||||
ChatItem(
|
||||
chatDir = CIDirection.DirectRcv(),
|
||||
meta = CIMeta.getSample(id, Clock.System.now(), text = ""),
|
||||
content = CIContent.RcvMsgContent(MsgContent.MCImage(text = "", image = "")),
|
||||
reactions = emptyList(),
|
||||
file = CIFile.getSample(fileId = id, fileName = "img-$id.jpg", filePath = "img-$id.jpg"),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user