New feature: flashlight (#61)
This commit is contained in:
@@ -18,6 +18,7 @@ import android.graphics.Bitmap
|
||||
import android.util.Log
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.widget.LinearLayout
|
||||
import androidx.camera.core.CameraControl
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.core.ImageCapture
|
||||
@@ -136,7 +137,9 @@ fun bindCameraUseCases(
|
||||
captureController.imageCapture = imageCapture
|
||||
|
||||
val cameraProvider = cameraProviderFuture.get()
|
||||
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, imageAnalysis, preview, imageCapture)
|
||||
val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector,
|
||||
imageAnalysis, preview, imageCapture)
|
||||
captureController.cameraControl = camera.cameraControl
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -197,6 +200,7 @@ fun replaceColor(bitmap: Bitmap, toReplace: Color, replacement: Color): Bitmap {
|
||||
fun Point.toOffset() = Offset(x.toFloat(), y.toFloat())
|
||||
|
||||
class CameraCaptureController {
|
||||
var cameraControl: CameraControl? = null
|
||||
var imageCapture: ImageCapture? = null
|
||||
private val executor = Executors.newSingleThreadExecutor()
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material.icons.filled.FlashOff
|
||||
import androidx.compose.material.icons.filled.FlashOn
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
@@ -93,7 +97,8 @@ data class CameraUiState(
|
||||
val captureState: CaptureState,
|
||||
val showDetectionError: Boolean,
|
||||
val isLandscape: Boolean,
|
||||
val isDebugMode: Boolean
|
||||
val isDebugMode: Boolean,
|
||||
val isTorchEnabled: Boolean,
|
||||
)
|
||||
|
||||
const val CAPTURED_IMAGE_DISPLAY_DURATION = 1500L
|
||||
@@ -112,6 +117,7 @@ fun CameraScreen(
|
||||
val document by viewModel.documentUiModel.collectAsStateWithLifecycle()
|
||||
val thumbnailCoords = remember { mutableStateOf(Offset.Zero) }
|
||||
var isDebugMode by remember { mutableStateOf(false) }
|
||||
var isTorchEnabled by remember { mutableStateOf(false) }
|
||||
|
||||
BackHandler { navigation.back() }
|
||||
|
||||
@@ -168,7 +174,8 @@ fun CameraScreen(
|
||||
captureState,
|
||||
showDetectionError,
|
||||
isLandscape = isLandscape,
|
||||
isDebugMode),
|
||||
isDebugMode,
|
||||
isTorchEnabled),
|
||||
onCapture = {
|
||||
previewView?.bitmap?.let {
|
||||
Log.i("FairScan", "Pressed <Capture>")
|
||||
@@ -180,6 +187,9 @@ fun CameraScreen(
|
||||
},
|
||||
onFinalizePressed = onFinalizePressed,
|
||||
onDebugModeSwitched = { isDebugMode = !isDebugMode },
|
||||
onTorchSwitched = {
|
||||
isTorchEnabled = !isTorchEnabled
|
||||
captureController.cameraControl?.enableTorch(isTorchEnabled) },
|
||||
thumbnailCoords = thumbnailCoords,
|
||||
navigation = navigation
|
||||
)
|
||||
@@ -193,6 +203,7 @@ private fun CameraScreenScaffold(
|
||||
onCapture: () -> Unit,
|
||||
onFinalizePressed: () -> Unit,
|
||||
onDebugModeSwitched: () -> Unit,
|
||||
onTorchSwitched: () -> Unit,
|
||||
thumbnailCoords: MutableState<Offset>,
|
||||
navigation: Navigation,
|
||||
) {
|
||||
@@ -225,6 +236,7 @@ private fun CameraScreenScaffold(
|
||||
cameraPreview,
|
||||
cameraUiState,
|
||||
onCapture,
|
||||
onTorchSwitched,
|
||||
modifier.clickable(onClick = onPageCountClick))
|
||||
}
|
||||
if (cameraUiState.captureState is CaptureState.CapturePreview) {
|
||||
@@ -238,6 +250,7 @@ private fun CameraPreviewBox(
|
||||
cameraPreview: @Composable (() -> Unit),
|
||||
cameraUiState: CameraUiState,
|
||||
onCapture: () -> Unit,
|
||||
onTorchSwitched: () -> Unit,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
Box(
|
||||
@@ -257,6 +270,20 @@ private fun CameraPreviewBox(
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(16.dp)
|
||||
)
|
||||
IconButton(
|
||||
onClick = onTorchSwitched,
|
||||
modifier = Modifier.align(Alignment.BottomStart)
|
||||
) {
|
||||
val torchEnabled = cameraUiState.isTorchEnabled
|
||||
val icon = if (torchEnabled) Icons.Default.FlashOn else Icons.Default.FlashOff
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription =
|
||||
stringResource(
|
||||
if (torchEnabled) R.string.turn_off_torch else R.string.turn_on_torch),
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,10 +506,11 @@ private fun ScreenPreview(captureState: CaptureState, rotationDegrees: Float = 0
|
||||
listState = LazyListState(),
|
||||
),
|
||||
cameraUiState = CameraUiState(pageCount = 4, LiveAnalysisState(), captureState,
|
||||
false, rotationDegrees > 0, false),
|
||||
false, rotationDegrees > 0, false, false),
|
||||
onCapture = {},
|
||||
onFinalizePressed = {},
|
||||
onDebugModeSwitched = {},
|
||||
onTorchSwitched = {},
|
||||
thumbnailCoords = thumbnailCoords,
|
||||
navigation = dummyNavigation()
|
||||
)
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
<string name="share">Sdílet</string>
|
||||
<string name="share_pdf">Sdílet PDF</string>
|
||||
<string name="storage_permission_denied">Nelze uložit PDF: přístup zakázán</string>
|
||||
<string name="turn_off_torch">Vypnout svítilnu</string>
|
||||
<string name="turn_on_torch">Zapnout svítilnu</string>
|
||||
<string name="unknown_size">Neznámá velikost</string>
|
||||
<string name="version">Verze</string>
|
||||
<string name="view_the_full_license">Zobrazit úplnou licenci</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">Teilen</string>
|
||||
<string name="share_pdf">PDF teilen</string>
|
||||
<string name="storage_permission_denied">PDF-Datei kann nicht gespeichert werden: Berechtigung verweigert</string>
|
||||
<string name="turn_off_torch">Taschenlampe ausschalten</string>
|
||||
<string name="turn_on_torch">Taschenlampe einschalten</string>
|
||||
<string name="unknown_size">Unbekannte Größe</string>
|
||||
<string name="version">Version</string>
|
||||
<string name="view_the_full_license">Vollständige Lizenz anzeigen</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">Compartir</string>
|
||||
<string name="share_pdf">Compartir PDF</string>
|
||||
<string name="storage_permission_denied">No se puede guardar el archivo PDF: permiso denegado</string>
|
||||
<string name="turn_off_torch">Apagar linterna</string>
|
||||
<string name="turn_on_torch">Encender linterna</string>
|
||||
<string name="unknown_size">Tamaño desconocido</string>
|
||||
<string name="version">Versión</string>
|
||||
<string name="view_the_full_license">Ver la licencia completa</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">Partager</string>
|
||||
<string name="share_pdf">Partager le PDF</string>
|
||||
<string name="storage_permission_denied">Impossible d’enregistrer le fichier PDF : permission refusée</string>
|
||||
<string name="turn_off_torch">Éteindre la torche</string>
|
||||
<string name="turn_on_torch">Allumer la torche</string>
|
||||
<string name="unknown_size">Taille inconnue</string>
|
||||
<string name="version">Version</string>
|
||||
<string name="view_the_full_license">Voir la licence complète</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">Condividi</string>
|
||||
<string name="share_pdf">Condividi PDF</string>
|
||||
<string name="storage_permission_denied">Impossibile salvare il file PDF: autorizzazione negata</string>
|
||||
<string name="turn_off_torch">Spegni la torcia</string>
|
||||
<string name="turn_on_torch">Accendi la torcia</string>
|
||||
<string name="unknown_size">Dimensione sconosciuta</string>
|
||||
<string name="version">Versione</string>
|
||||
<string name="view_the_full_license">Vedi la licenza completa</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">Compartilhar</string>
|
||||
<string name="share_pdf">Compartilhar PDF</string>
|
||||
<string name="storage_permission_denied">Não foi possível salvar o arquivo PDF: permissão negada</string>
|
||||
<string name="turn_off_torch">Desligar lanterna</string>
|
||||
<string name="turn_on_torch">Ligar lanterna</string>
|
||||
<string name="unknown_size">Tamanho desconhecido</string>
|
||||
<string name="version">Versão</string>
|
||||
<string name="view_the_full_license">Ver licença completa</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">Поделиться</string>
|
||||
<string name="share_pdf">Поделиться PDF</string>
|
||||
<string name="storage_permission_denied">Не удается сохранить файл PDF: в разрешении отказано</string>
|
||||
<string name="turn_off_torch">Выключить фонарик</string>
|
||||
<string name="turn_on_torch">Включить фонарик</string>
|
||||
<string name="unknown_size">Неизвестный размер</string>
|
||||
<string name="version">Версия</string>
|
||||
<string name="view_the_full_license">Просмотреть полную лицензию</string>
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
<string name="share">共享</string>
|
||||
<string name="share_pdf">共享 PDF</string>
|
||||
<string name="storage_permission_denied">无法保存PDF文件:权限被拒绝</string>
|
||||
<string name="turn_off_torch">关闭手电筒</string>
|
||||
<string name="turn_on_torch">打开手电筒</string>
|
||||
<string name="unknown_size">未知大小</string>
|
||||
<string name="version">版本</string>
|
||||
<string name="view_the_full_license">查看完整许可证</string>
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
<string name="share">Share</string>
|
||||
<string name="share_pdf">Share PDF</string>
|
||||
<string name="storage_permission_denied">Cannot save PDF file: permission was denied</string>
|
||||
<string name="turn_off_torch">Turn off torch</string>
|
||||
<string name="turn_on_torch">Turn on torch</string>
|
||||
<string name="unknown_size">Unknown size</string>
|
||||
<string name="version">Version</string>
|
||||
<string name="view_the_full_license">View the full license</string>
|
||||
|
||||
Reference in New Issue
Block a user