mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
fix: stop the media dialog clobbering its window attributes every frame
ZoomableImageDialog copied the activity window's attributes onto the dialog window inline in composition. That content recomposes on every frame of a pager swipe (it reads the image bounds the pager moves), so a swipe sent ~60 attribute updates to the window manager, and each one overwrote the dialog's own colorMode and desiredHdrHeadroom with the feed's. On a Pixel 9a that capped fullscreen HDR photos at the feed's 2x, kept an SDR page in HDR mode (ratio 5), and made swiping back to an HDR photo land in SDR depending on timing. Run the copy in an effect keyed on orientation and the two windows, and preserve the dialog's colorMode and HDR headroom alongside the brightness override it already kept. Measured after: HDR page 5, SDR page 1, HDR again 5, stable across repeated swipes.
This commit is contained in:
+25
-14
@@ -21,6 +21,7 @@
|
||||
package com.vitorpamplona.amethyst.ui.components
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.WindowManager
|
||||
@@ -44,6 +45,7 @@ import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -182,20 +184,29 @@ fun ZoomableImageDialog(
|
||||
val activityWindow = getActivityWindow()
|
||||
val dialogWindow = getDialogWindow()
|
||||
|
||||
if (activityWindow != null && dialogWindow != null) {
|
||||
// Preserve any brightness override already applied to the dialog window (e.g. by the
|
||||
// fullscreen swipe controls). This block re-runs on recomposition (orientation change
|
||||
// re-reads `orientation` above), and copying the activity attributes would otherwise
|
||||
// reset screenBrightness and snap the user's brightness back mid-session.
|
||||
val currentBrightness = dialogWindow.attributes.screenBrightness
|
||||
val attributes = WindowManager.LayoutParams()
|
||||
attributes.copyFrom(activityWindow.attributes)
|
||||
attributes.type = dialogWindow.attributes.type
|
||||
// Disable the system dim so the thumbnail stays visible behind the growing dialog.
|
||||
attributes.dimAmount = 0f
|
||||
attributes.flags = attributes.flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()
|
||||
attributes.screenBrightness = currentBrightness
|
||||
dialogWindow.attributes = attributes
|
||||
// Keyed, not inline: this content recomposes on every frame of a pager swipe (the image
|
||||
// bounds it reads move), and each assignment below is a window-manager round trip.
|
||||
DisposableEffect(orientation, activityWindow, dialogWindow) {
|
||||
if (activityWindow != null && dialogWindow != null) {
|
||||
// Preserve what the dialog window owns: the brightness override applied by the
|
||||
// fullscreen swipe controls, and the HDR mode [RequestHdrFor] manages for the
|
||||
// image on screen. Copying the activity's instead would snap brightness back
|
||||
// mid-session and cap or force HDR by whatever the feed behind happens to show.
|
||||
val current = dialogWindow.attributes
|
||||
val attributes = WindowManager.LayoutParams()
|
||||
attributes.copyFrom(activityWindow.attributes)
|
||||
attributes.type = current.type
|
||||
// Disable the system dim so the thumbnail stays visible behind the growing dialog.
|
||||
attributes.dimAmount = 0f
|
||||
attributes.flags = attributes.flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()
|
||||
attributes.screenBrightness = current.screenBrightness
|
||||
attributes.colorMode = current.colorMode
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||
attributes.desiredHdrHeadroom = current.desiredHdrHeadroom
|
||||
}
|
||||
dialogWindow.attributes = attributes
|
||||
}
|
||||
onDispose {}
|
||||
}
|
||||
|
||||
// Go fully immersive while the full-screen media viewer is open. Applies to full-screen
|
||||
|
||||
Reference in New Issue
Block a user