Skip to content

Commit

Permalink
Extract PeekabooCameraView and PeekabooGalleryView components in samp…
Browse files Browse the repository at this point in the history
…le app
  • Loading branch information
onseok committed Feb 5, 2024
1 parent 84b028e commit 4e52bf4
Show file tree
Hide file tree
Showing 3 changed files with 284 additions and 135 deletions.
203 changes: 68 additions & 135 deletions sample/common/src/commonMain/kotlin/com/preat/peekaboo/common/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,17 @@
package com.preat.peekaboo.common

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState
Expand All @@ -47,25 +40,17 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.preat.peekaboo.common.component.CircularButton
import com.preat.peekaboo.common.component.InstagramCameraButton
import com.preat.peekaboo.common.icon.IconCached
import com.preat.peekaboo.common.icon.IconClose
import com.preat.peekaboo.common.icon.IconWarning
import com.preat.peekaboo.common.component.PeekabooCameraView
import com.preat.peekaboo.common.component.PeekabooGalleryView
import com.preat.peekaboo.common.style.PeekabooTheme
import com.preat.peekaboo.image.picker.FilterOptions
import com.preat.peekaboo.image.picker.ResizeOptions
import com.preat.peekaboo.image.picker.SelectionMode
import com.preat.peekaboo.image.picker.rememberImagePickerLauncher
import com.preat.peekaboo.image.picker.toImageBitmap
import com.preat.peekaboo.ui.CameraMode
import com.preat.peekaboo.ui.PeekabooCamera
import kotlinx.coroutines.launch

@Suppress("FunctionName")
@Composable
Expand All @@ -74,6 +59,7 @@ fun App() {
var images by remember { mutableStateOf(listOf<ImageBitmap>()) }
val snackbarHostState = remember { SnackbarHostState() }
var showCamera by remember { mutableStateOf(false) }
var showGallery by remember { mutableStateOf(false) }

val singleImagePicker =
rememberImagePickerLauncher(
Expand Down Expand Up @@ -112,130 +98,77 @@ fun App() {
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
if (showCamera) {
Box {
if (showCamera) {
PeekabooCamera(
modifier = Modifier.fillMaxSize(),
cameraMode = CameraMode.Back,
captureIcon = { onClick ->
InstagramCameraButton(
modifier =
Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 16.dp),
onClick = onClick,
)
},
convertIcon = { onClick ->
CircularButton(
imageVector = IconCached,
modifier =
Modifier
.align(Alignment.BottomEnd)
.padding(bottom = 16.dp, end = 16.dp),
onClick = onClick,
)
},
progressIndicator = {
CircularProgressIndicator(
modifier =
Modifier
.size(80.dp)
.align(Alignment.Center),
color = Color.White.copy(alpha = 0.7f),
strokeWidth = 8.dp,
)
},
onCapture = { byteArray ->
byteArray?.let {
images = listOf(it.toImageBitmap())
} ?: scope.launch {
snackbarHostState.showSnackbar(
message =
"Unable to capture the image. Please try again.",
)
}
showCamera = false
},
permissionDeniedContent = {
Column(
modifier =
Modifier
.fillMaxSize()
.background(color = MaterialTheme.colors.background),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Icon(
imageVector = IconWarning,
contentDescription = "Warning Icon",
tint = MaterialTheme.colors.onBackground,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Please grant the camera permission!",
color = MaterialTheme.colors.onBackground,
textAlign = TextAlign.Center,
)
}
},
)
when {
showCamera -> {
PeekabooCameraView(
modifier = Modifier.fillMaxSize(),
onBack = { showCamera = false },
onCapture = { byteArray ->
byteArray?.let {
images = listOf(it.toImageBitmap())
}
showCamera = false
},
)
}
showGallery -> {
PeekabooGalleryView(
modifier = Modifier.fillMaxSize(),
onBack = { showGallery = false },
onImageSelected = { byteArray ->
byteArray?.let {
images = listOf(it.toImageBitmap())
}
showGallery = false
},
)
}
else -> {
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = 8.dp),
) {
items(images) { image ->
Image(
bitmap = image,
contentDescription = "Selected Image",
modifier =
Modifier
.size(200.dp)
.clip(shape = RoundedCornerShape(12.dp)),
contentScale = ContentScale.Crop,
)
}
}
IconButton(
Spacer(modifier = Modifier.height(20.dp))
Button(
onClick = {
showCamera = false
singleImagePicker.launch()
},
modifier =
Modifier
.align(Alignment.TopStart)
.padding(top = 16.dp, start = 16.dp),
) {
Icon(
imageVector = IconClose,
contentDescription = "Back Button",
tint = Color.White,
)
Text("Pick Single Image")
}
}
} else {
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = 8.dp),
) {
items(images) { image ->
Image(
bitmap = image,
contentDescription = "Selected Image",
modifier =
Modifier
.size(200.dp)
.clip(shape = RoundedCornerShape(12.dp)),
contentScale = ContentScale.Crop,
)
Button(
onClick = {
multipleImagePicker.launch()
},
) {
Text("Pick Multiple Images")
}
Button(
onClick = {
showCamera = true
},
) {
Text("Capture Image from Camera")
}
Button(
onClick = {
showGallery = true
},
) {
Text("Pick Image from Gallery")
}
}
Spacer(modifier = Modifier.height(20.dp))
Button(
onClick = {
singleImagePicker.launch()
},
) {
Text("Pick Single Image")
}
Button(
onClick = {
multipleImagePicker.launch()
},
) {
Text("Pick Multiple Images")
}
Button(
onClick = {
showCamera = true
},
) {
Text("Capture Image from Camera")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright 2024 onseok
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.preat.peekaboo.common.component

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.preat.peekaboo.common.icon.IconCached
import com.preat.peekaboo.common.icon.IconClose
import com.preat.peekaboo.common.icon.IconWarning
import com.preat.peekaboo.ui.camera.CameraMode
import com.preat.peekaboo.ui.camera.PeekabooCamera

@Suppress("FunctionName")
@Composable
internal fun PeekabooCameraView(
modifier: Modifier = Modifier,
onCapture: (ByteArray?) -> Unit,
onBack: () -> Unit,
) {
Box(modifier = modifier) {
PeekabooCamera(
modifier = Modifier.fillMaxSize(),
cameraMode = CameraMode.Back,
captureIcon = { onClick ->
InstagramCameraButton(
modifier =
Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 16.dp),
onClick = onClick,
)
},
convertIcon = { onClick ->
CircularButton(
imageVector = IconCached,
modifier =
Modifier
.align(Alignment.BottomEnd)
.padding(bottom = 16.dp, end = 16.dp),
onClick = onClick,
)
},
progressIndicator = {
CircularProgressIndicator(
modifier =
Modifier
.size(80.dp)
.align(Alignment.Center),
color = Color.White.copy(alpha = 0.7f),
strokeWidth = 8.dp,
)
},
onCapture = onCapture,
permissionDeniedContent = {
Column(
modifier =
Modifier
.fillMaxSize()
.background(color = MaterialTheme.colors.background),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Icon(
imageVector = IconWarning,
contentDescription = "Warning Icon",
tint = MaterialTheme.colors.onBackground,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Please grant the camera permission!",
color = MaterialTheme.colors.onBackground,
textAlign = TextAlign.Center,
)
}
},
)
IconButton(
onClick = onBack,
modifier =
Modifier
.align(Alignment.TopStart)
.padding(top = 16.dp, start = 16.dp),
) {
Icon(
imageVector = IconClose,
contentDescription = "Back Button",
tint = Color.White,
)
}
}
}
Loading

0 comments on commit 4e52bf4

Please sign in to comment.