Skip to content

Commit

Permalink
Update project
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbel committed Nov 21, 2023
1 parent 2cc1e7c commit 756b070
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 142 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.michaelbel.movies.gallery.ui

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import org.michaelbel.movies.ui.preview.DevicePreviews
import org.michaelbel.movies.ui.theme.MoviesTheme

@Composable
fun GalleryLoading(
modifier: Modifier = Modifier
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
LinearProgressIndicator(
modifier = Modifier,
trackColor = MaterialTheme.colorScheme.inversePrimary
)
}
}

@Composable
@DevicePreviews
private fun GalleryLoadingPreview() {
MoviesTheme {
GalleryLoading(
modifier = Modifier.fillMaxSize()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,176 +150,183 @@ private fun GalleryScreenContent(
},
containerColor = MaterialTheme.colorScheme.primaryContainer
) { paddingValues ->
ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (pager, backIcon, title) = createRefs()
when {
movieImages.isEmpty() -> {
GalleryLoading(
modifier = Modifier.fillMaxSize()
)
}
else -> {
ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (pager, backIcon, title) = createRefs()

val initialPage = 0
val pagerState = rememberPagerState(
initialPage = initialPage,
initialPageOffsetFraction = 0F,
pageCount = { movieImages.size }
)
val initialPage = 0
val pagerState = rememberPagerState(
initialPage = initialPage,
initialPageOffsetFraction = 0F,
pageCount = { movieImages.size }
)

var currentPage: Int by remember { mutableStateOf(0) }
LaunchedEffect(pagerState) {
snapshotFlow { pagerState.currentPage }.collect { page ->
if (currentPage != page) {
hapticFeedback.performHapticFeedback(hapticFeedbackType = HapticFeedbackType.LongPress)
currentPage = page
var currentPage: Int by remember { mutableStateOf(0) }
LaunchedEffect(pagerState) {
snapshotFlow { pagerState.currentPage }.collect { page ->
if (currentPage != page) {
hapticFeedback.performHapticFeedback(hapticFeedbackType = HapticFeedbackType.LongPress)
currentPage = page
}
}
}
}
}

LoopHorizontalPager(
pagerState = pagerState,
modifier = Modifier.constrainAs(pager) {
width = Dimension.fillToConstraints
height = Dimension.wrapContent
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
) { page ->
currentPage = page
LoopHorizontalPager(
pagerState = pagerState,
modifier = Modifier.constrainAs(pager) {
width = Dimension.fillToConstraints
height = Dimension.wrapContent
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
) { page ->
currentPage = page

val imageDb: ImageDb = movieImages[page]
var imageDiskCacheKey: String? by remember { mutableStateOf(null) }
val imageDb: ImageDb = movieImages[page]
var imageDiskCacheKey: String? by remember { mutableStateOf(null) }

var image: String by remember { mutableStateOf("") }
image = imageDb.original
var image: String by remember { mutableStateOf("") }
image = imageDb.original

var loading: Boolean by remember { mutableStateOf(true) }
var loading: Boolean by remember { mutableStateOf(true) }

ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (asyncImage, progressBar, downloadIcon) = createRefs()
ConstraintLayout(
modifier = Modifier.fillMaxSize()
) {
val (asyncImage, progressBar, downloadIcon) = createRefs()

val zoomState = rememberZoomState()
val zoomState = rememberZoomState()

AsyncImage(
model = ImageRequest.Builder(context)
.data(image)
.crossfade(true)
.placeholderMemoryCacheKey(imageDiskCacheKey)
.build(),
contentDescription = null,
modifier = Modifier
.constrainAs(asyncImage) {
width = Dimension.fillToConstraints
height = Dimension.fillToConstraints
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
AsyncImage(
model = ImageRequest.Builder(context)
.data(image)
.crossfade(true)
.placeholderMemoryCacheKey(imageDiskCacheKey)
.build(),
contentDescription = null,
modifier = Modifier
.constrainAs(asyncImage) {
width = Dimension.fillToConstraints
height = Dimension.fillToConstraints
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.zoomable(zoomState),
transform = { state ->
loading = state is AsyncImagePainter.State.Loading

if (state is AsyncImagePainter.State.Success) {
zoomState.setContentSize(state.painter.intrinsicSize)
imageDiskCacheKey = state.result.diskCacheKey
if (image.isNotOriginal) {
image = imageDb.original
}
}

state
},
contentScale = ContentScale.Fit
)

if (loading) {
LinearProgressIndicator(
modifier = Modifier
.constrainAs(progressBar) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.zoomable(zoomState),
trackColor = MaterialTheme.colorScheme.inversePrimary
)
}
.zoomable(zoomState),
transform = { state ->
loading = state is AsyncImagePainter.State.Loading

if (state is AsyncImagePainter.State.Success) {
zoomState.setContentSize(state.painter.intrinsicSize)
imageDiskCacheKey = state.result.diskCacheKey
if (image.isNotOriginal) {
image = imageDb.original
AnimatedVisibility(
visible = !loading,
modifier = Modifier
.constrainAs(downloadIcon) {
width = Dimension.wrapContent
height = Dimension.wrapContent
end.linkTo(parent.end, 4.dp)
top.linkTo(parent.top, 8.dp)
}
.statusBarsPadding(),
enter = fadeIn()
) {
IconButton(
onClick = { onDownloadClick(imageDb) },
modifier = Modifier.windowInsetsPadding(displayCutoutWindowInsets)
) {
Image(
imageVector = MoviesIcons.FileDownload,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimaryContainer)
)
}
}

state
},
contentScale = ContentScale.Fit
)

if (loading) {
LinearProgressIndicator(
modifier = Modifier
.constrainAs(progressBar) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.zoomable(zoomState),
trackColor = MaterialTheme.colorScheme.inversePrimary
)
BackHandler(zoomState.isScaled) {
coroutineScope.launch { zoomState.reset() }
}
}
}

AnimatedVisibility(
visible = !loading,
IconButton(
onClick = onBackClick,
modifier = Modifier
.constrainAs(downloadIcon) {
.constrainAs(backIcon) {
width = Dimension.wrapContent
height = Dimension.wrapContent
end.linkTo(parent.end, 4.dp)
start.linkTo(parent.start, 4.dp)
top.linkTo(parent.top, 8.dp)
}
.statusBarsPadding(),
enter = fadeIn()
.statusBarsPadding()
.windowInsetsPadding(displayCutoutWindowInsets)
) {
IconButton(
onClick = { onDownloadClick(imageDb) },
modifier = Modifier.windowInsetsPadding(displayCutoutWindowInsets)
) {
Image(
imageVector = MoviesIcons.FileDownload,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimaryContainer)
)
}
Image(
imageVector = MoviesIcons.ArrowBack,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimaryContainer)
)
}

BackHandler(zoomState.isScaled) {
coroutineScope.launch { zoomState.reset() }
}
Text(
text = "",
modifier = Modifier
.constrainAs(title) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(backIcon.end, 4.dp)
top.linkTo(backIcon.top)
end.linkTo(parent.end, 4.dp)
bottom.linkTo(backIcon.bottom)
}
.statusBarsPadding(),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
textAlign = TextAlign.Start,
style = MaterialTheme.typography.titleLarge.copy(
color = MaterialTheme.colorScheme.onPrimaryContainer
)
)
}
}

IconButton(
onClick = onBackClick,
modifier = Modifier
.constrainAs(backIcon) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(parent.start, 4.dp)
top.linkTo(parent.top, 8.dp)
}
.statusBarsPadding()
.windowInsetsPadding(displayCutoutWindowInsets)
) {
Image(
imageVector = MoviesIcons.ArrowBack,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimaryContainer)
)
}

Text(
text = "",
modifier = Modifier
.constrainAs(title) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(backIcon.end, 4.dp)
top.linkTo(backIcon.top)
end.linkTo(parent.end, 4.dp)
bottom.linkTo(backIcon.bottom)
}
.statusBarsPadding(),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
textAlign = TextAlign.Start,
style = MaterialTheme.typography.titleLarge.copy(
color = MaterialTheme.colorScheme.onPrimaryContainer
)
)
}

paddingValues.toString()
}
}

Expand Down

0 comments on commit 756b070

Please sign in to comment.