Do not enlarge images on open

This commit is contained in:
iris committed 2026-09-12 21:52:47 -04:00
1 parent 6d765ff6e4
commit e9a0f1b9da
3 files changed
+26 -15

No files matched your search

+2 -1
View File
@@ -1048,7 +1048,8 @@ dev-updater (Kotlin 2.4.x, CMP 1.11.x, JDK 21).
system-bar regions** (2026-09-12). It hides the status and navigation bars
independently when the fitted, zoomed or panned image reaches them, and
restores either one when it does not. `100%` recenters at one bitmap pixel
per screen pixel; opening still fits the whole image first.
per screen pixel; opening only shrinks an image that needs it to fit and
never enlarges a smaller one.
- **All transcript text is selectable, from one `SelectionContainer`
around the whole list.** Not per row: a transcript is one body of text,
so a selection has to run from a reply into the tool output under it —
@@ -292,7 +292,8 @@ private fun enlargingFilter(sourceHeight: Int, drawnHeight: Int): FilterQuality
*
* Inside a dialog rather than a screen -- see [SessionImageViewer] -- so the platform's back
* gesture returns to the transcript instead of leaving the app. It opens fitted, with the whole
* image visible; the 100% control changes to one bitmap pixel per screen pixel and recenters it.
* image visible without enlarging a smaller one; the 100% control changes to one bitmap pixel per
* screen pixel and recenters it.
*/
@Composable
private fun ZoomableImage(
@@ -328,7 +329,7 @@ private fun ZoomableImage(
Image(
bitmap = image,
contentDescription = "Attached image",
contentScale = ContentScale.Fit,
contentScale = ContentScale.Inside,
// Zoomed in, the reader is looking at pixels on purpose.
filterQuality = FilterQuality.None,
modifier =
@@ -337,9 +338,8 @@ private fun ZoomableImage(
.pointerInput(nativeScale) {
detectTransformGestures { centroid, pan, zoom, _ ->
val oldScale = scale
val minimumScale = minOf(1f, nativeScale)
val maximumScale = maxOf(8f, nativeScale)
val newScale = (oldScale * zoom).coerceIn(minimumScale, maximumScale)
val newScale = (oldScale * zoom).coerceIn(1f, maximumScale)
if (newScale > 1f) {
val offset =
zoomOffset(
@@ -414,8 +414,7 @@ internal fun viewerBars(
if (imageWidth <= 0 || imageHeight <= 0 || viewportWidth <= 0 || viewportHeight <= 0) {
return ViewerBars()
}
val fittedScale =
minOf(viewportWidth.toFloat() / imageWidth, viewportHeight.toFloat() / imageHeight)
val fittedScale = insideScale(imageWidth, imageHeight, viewportWidth, viewportHeight)
val width = imageWidth * fittedScale * scale
val height = imageHeight * fittedScale * scale
val left = viewportWidth / 2f + offset.x - width / 2f
@@ -433,7 +432,7 @@ internal fun viewerBars(
)
}
/** Scale relative to [ContentScale.Fit] at which bitmap and screen pixels are one-to-one. */
/** Scale relative to [ContentScale.Inside] at which bitmap and screen pixels are one-to-one. */
internal fun nativeScale(
imageWidth: Int,
imageHeight: Int,
@@ -441,11 +440,22 @@ internal fun nativeScale(
viewportHeight: Int,
): Float {
if (imageWidth <= 0 || imageHeight <= 0 || viewportWidth <= 0 || viewportHeight <= 0) return 1f
val fittedScale =
minOf(viewportWidth.toFloat() / imageWidth, viewportHeight.toFloat() / imageHeight)
return 1f / fittedScale
return 1f / insideScale(imageWidth, imageHeight, viewportWidth, viewportHeight)
}
/** The downscale-only factor used by [ContentScale.Inside]. */
private fun insideScale(
imageWidth: Int,
imageHeight: Int,
viewportWidth: Int,
viewportHeight: Int,
): Float =
minOf(
1f,
viewportWidth.toFloat() / imageWidth,
viewportHeight.toFloat() / imageHeight,
)
/** Keeps the image point beneath [centroid] beneath the fingers as its scale changes. */
internal fun zoomOffset(
offset: Offset,
@@ -10,8 +10,8 @@ class SessionImageTest {
assertEquals(
ViewerBars(status = true, navigation = true),
viewerBars(
imageWidth = 500,
imageHeight = 1000,
imageWidth = 1000,
imageHeight = 2000,
viewportWidth = 1000,
viewportHeight = 2000,
scale = 1f,
@@ -67,9 +67,9 @@ class SessionImageTest {
}
@Test
fun `native scale reverses enlarging a small image`() {
fun `native scale leaves a small image alone`() {
assertEquals(
0.5f,
1f,
nativeScale(
imageWidth = 500,
imageHeight = 500,