mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-08-14 01:03:28 +01:00
Report focused media from the pager rather than the thumbnail rail in media-send.
This commit is contained in:
+22
-3
@@ -30,7 +30,9 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -40,6 +42,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.compose.AndroidFragment
|
||||
import androidx.lifecycle.ViewModelStoreOwner
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.ui.WindowBreakpoint
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
@@ -100,6 +104,24 @@ internal fun MediaEditScreen(
|
||||
}
|
||||
}
|
||||
|
||||
// Read through the latest selection rather than the one captured when the effect below started, since removals and
|
||||
// reordering change which media a settled page refers to without restarting it.
|
||||
val currentSelectedMedia by rememberUpdatedState(state.selectedMedia)
|
||||
|
||||
// Focus belongs to the pager rather than to any one piece of chrome: the thumbnail rail is not composed for
|
||||
// documents, and a swipe still has to be reported from there.
|
||||
LaunchedEffect(pagerState) {
|
||||
snapshotFlow { pagerState.isScrollInProgress }
|
||||
.filter { !it }
|
||||
.drop(1)
|
||||
.collect {
|
||||
val settledMedia = currentSelectedMedia.getOrNull(pagerState.currentPage)
|
||||
if (settledMedia != null) {
|
||||
onEvent(MediaEditScreenEvents.FocusedMediaChanged(settledMedia))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// During a camera-first flow, backing out of edit when the only selection is the capture itself should discard the
|
||||
// capture and return to the camera rather than leaving the empty editor on the back stack.
|
||||
val isOnlyCameraFirstCapture = state.cameraFirstCapture != null &&
|
||||
@@ -281,9 +303,6 @@ internal fun MediaEditScreen(
|
||||
selectedMedia = state.selectedMedia,
|
||||
pagerState = pagerState,
|
||||
enabled = !isInteracting,
|
||||
onFocusedMediaChange = {
|
||||
onEvent(MediaEditScreenEvents.FocusedMediaChanged(it))
|
||||
},
|
||||
onThumbnailClick = { index ->
|
||||
if (pagerState.currentPage == index) {
|
||||
onEvent(MediaEditScreenEvents.RemoveMedia(state.selectedMedia[index]))
|
||||
|
||||
@@ -29,7 +29,6 @@ import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -42,8 +41,6 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.models.media.Media
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
@@ -67,12 +64,14 @@ private val MAX_PADDING = 8.dp
|
||||
/**
|
||||
* Horizontally scrollable thumbnail strip that syncs with [pagerState].
|
||||
* Features fish-eye padding effect where the centered item has more padding.
|
||||
*
|
||||
* Dragging the strip scrolls the pager, and which media the settled page focuses is reported by the caller from
|
||||
* [pagerState] rather than from here, since this row is only one of the chromes the pager can be swiped beneath.
|
||||
*/
|
||||
@Composable
|
||||
internal fun ThumbnailRow(
|
||||
selectedMedia: List<Media>,
|
||||
pagerState: PagerState,
|
||||
onFocusedMediaChange: (Media) -> Unit,
|
||||
onThumbnailClick: (Int) -> Unit = {},
|
||||
onReorder: (fromIndex: Int, toIndex: Int) -> Unit = { _, _ -> },
|
||||
enabled: Boolean = true
|
||||
@@ -102,22 +101,6 @@ internal fun ThumbnailRow(
|
||||
pagerState.dispatchRawDelta(-scaledDelta)
|
||||
}
|
||||
|
||||
// Read through the latest selection rather than the one captured when the effect started, since reordering changes
|
||||
// which media a settled page refers to without restarting the effect.
|
||||
val currentSelectedMedia by rememberUpdatedState(selectedMedia)
|
||||
|
||||
LaunchedEffect(pagerState) {
|
||||
snapshotFlow { pagerState.isScrollInProgress }
|
||||
.filter { !it }
|
||||
.drop(1)
|
||||
.collectLatest {
|
||||
val settledPage = pagerState.currentPage
|
||||
if (settledPage in currentSelectedMedia.indices) {
|
||||
onFocusedMediaChange(currentSelectedMedia[settledPage])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The rail's scroll position belongs to the drag rather than the pager from the moment an item is picked up until the
|
||||
// reorder it produced has landed in state. Resuming any earlier means syncing to the pre-drag order and then having to
|
||||
// correct once the new order arrives. The single catch-up afterwards is animated so the rail glides to the dropped
|
||||
@@ -169,10 +152,6 @@ internal fun ThumbnailRow(
|
||||
else -> pagerState.currentPage
|
||||
}
|
||||
pagerState.animateScrollToPage(targetPage)
|
||||
|
||||
if (targetPage in selectedMedia.indices) {
|
||||
onFocusedMediaChange(selectedMedia[targetPage])
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -275,8 +254,7 @@ private fun ThumbnailRowPreview() {
|
||||
Previews.Preview {
|
||||
ThumbnailRow(
|
||||
selectedMedia = media,
|
||||
pagerState = pagerState,
|
||||
onFocusedMediaChange = { }
|
||||
pagerState = pagerState
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user