fully working

This commit is contained in:
Henry Hiles 2023-03-20 13:10:24 -04:00
parent b51834635a
commit 532a613179
9 changed files with 142 additions and 19 deletions

View file

@ -0,0 +1,32 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
</profile>
</component>

6
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -43,7 +43,7 @@ android {
buildConfig = true buildConfig = true
} }
composeOptions { composeOptions {
kotlinCompilerExtensionVersion = "1.2.0" kotlinCompilerExtensionVersion = "1.4.3"
} }
packagingOptions { packagingOptions {
resources { resources {

View file

@ -0,0 +1,41 @@
package com.henryhiles.qscan
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun LabelledCheckBox(
checked: Boolean,
onCheckedChange: ((Boolean) -> Unit),
label: String,
modifier: Modifier = Modifier
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() },
onClick = { onCheckedChange(!checked) }
)
) {
Checkbox(
checked = checked,
onCheckedChange = null
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = label,
)
}
}

View file

@ -3,10 +3,13 @@
package com.henryhiles.qscan package com.henryhiles.qscan
import android.Manifest import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.util.Size import android.util.Size
import android.webkit.URLUtil import android.webkit.URLUtil
import android.widget.Toast
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
@ -20,6 +23,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -47,13 +51,26 @@ class MainActivity : ComponentActivity() {
} }
} }
//@OptIn(ExperimentalMaterial3Api::class)
@ExperimentalMaterial3Api
@Composable @Composable
fun Screen() { fun Screen() {
var code by remember { mutableStateOf("") } var code by remember { mutableStateOf("") }
val context = LocalContext.current val context = LocalContext.current
val lifeCycleOwner = LocalLifecycleOwner.current val lifeCycleOwner = LocalLifecycleOwner.current
val activity = lifeCycleOwner as Activity
val sharedPref = activity.getPreferences(Context.MODE_PRIVATE)
var doNotAsk by remember {
mutableStateOf(
sharedPref.getBoolean(
R.string.should_auto_open_key.toString(),
false
)
)
}
var prompted by remember {
mutableStateOf(false)
}
val uriHandler = LocalUriHandler.current
val cameraProviderFuture = remember { val cameraProviderFuture = remember {
ProcessCameraProvider.getInstance(context) ProcessCameraProvider.getInstance(context)
} }
@ -67,12 +84,31 @@ fun Screen() {
} }
val launcher = rememberLauncherForActivityResult( val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(), contract = ActivityResultContracts.RequestPermission(),
onResult = { granted -> hasCamPermission = granted } onResult = { granted ->
hasCamPermission = granted
prompted = true
}
) )
LaunchedEffect(key1 = true) { LaunchedEffect(key1 = true) {
launcher.launch(Manifest.permission.CAMERA) launcher.launch(Manifest.permission.CAMERA)
} }
LaunchedEffect(key1 = code) {
Toast.makeText(context, "Test $doNotAsk $code", Toast.LENGTH_LONG).show()
if (doNotAsk && URLUtil.isValidUrl(code)) {
uriHandler.openUri(code)
code = ""
}
}
LaunchedEffect(key1 = doNotAsk) {
with(sharedPref.edit()) {
putBoolean(R.string.should_auto_open_key.toString(), doNotAsk)
apply()
}
}
Column(modifier = Modifier.fillMaxSize()) { Column(modifier = Modifier.fillMaxSize()) {
if (hasCamPermission) { if (hasCamPermission) {
AndroidView( AndroidView(
@ -102,15 +138,10 @@ fun Screen() {
}, modifier = Modifier }, modifier = Modifier
.fillMaxSize() .fillMaxSize()
) )
if (code != "") { if (code != "" && !doNotAsk) {
val uriHandler = LocalUriHandler.current
val isURL = URLUtil.isValidUrl(code) val isURL = URLUtil.isValidUrl(code)
// val sharedPref =
// activity.getPreferences(Context.MODE_PRIVATE) var tempDoNotAsk by remember { mutableStateOf(false) }
// with(sharedPref.edit()) {
// putBoolean("", true)
// apply()
// }
AlertDialog(onDismissRequest = { code = "" }) { AlertDialog(onDismissRequest = { code = "" }) {
Surface( Surface(
@ -130,6 +161,14 @@ fun Screen() {
) )
} }
Row(verticalAlignment = Alignment.CenterVertically) {
LabelledCheckBox(
checked = tempDoNotAsk,
onCheckedChange = { tempDoNotAsk = it },
label = "Don't ask again"
)
}
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End horizontalArrangement = Arrangement.End
@ -141,7 +180,11 @@ fun Screen() {
) )
} }
if (isURL) if (isURL)
TextButton(onClick = { uriHandler.openUri(code) }) { TextButton(onClick = {
uriHandler.openUri(code)
doNotAsk = tempDoNotAsk
code = ""
}) {
Text( Text(
text = "Open URL", text = "Open URL",
style = MaterialTheme.typography.labelLarge style = MaterialTheme.typography.labelLarge
@ -152,7 +195,7 @@ fun Screen() {
} }
} }
} }
} else AlertDialog(onDismissRequest = {}) { } else if (prompted) AlertDialog(onDismissRequest = {}) {
Surface( Surface(
shape = MaterialTheme.shapes.large shape = MaterialTheme.shapes.large
) { ) {
@ -174,7 +217,9 @@ fun Screen() {
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End horizontalArrangement = Arrangement.End
) { ) {
TextButton(onClick = { }) { TextButton(onClick = {
launcher.launch(Manifest.permission.CAMERA)
}) {
Text( Text(
text = "Grant Permission", text = "Grant Permission",
style = MaterialTheme.typography.labelLarge style = MaterialTheme.typography.labelLarge

View file

@ -37,7 +37,7 @@ class QrCodeAnalyzer(private val onQrCodeScanned: (String) -> Unit) : ImageAnaly
}.decode(binaryBmp) }.decode(binaryBmp)
onQrCodeScanned(result.text) onQrCodeScanned(result.text)
} catch (e: Exception) { } catch (e: Exception) {
// Don't print anything // Don't do anything
} finally { } finally {
image.close() image.close()
} }

View file

@ -9,7 +9,6 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.core.view.ViewCompat
private val DarkColorScheme = darkColorScheme( private val DarkColorScheme = darkColorScheme(
primary = Purple80, primary = Purple80,
@ -52,7 +51,6 @@ fun QScanTheme(
if (!view.isInEditMode) { if (!view.isInEditMode) {
SideEffect { SideEffect {
(view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb() (view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
} }
} }

View file

@ -1,3 +1,4 @@
<resources> <resources>
<string name="app_name">QScan</string> <string name="app_name">QScan</string>
<string name="should_auto_open_key">AUTO_OPEN</string>
</resources> </resources>

View file

@ -1,5 +1,5 @@
plugins { plugins {
id("com.android.application") version "7.4.1" apply false id("com.android.application") version "7.4.1" apply false
id("com.android.library") version "7.4.1" apply false id("com.android.library") version "7.4.1" apply false
id("org.jetbrains.kotlin.android") version "1.7.0" apply false id("org.jetbrains.kotlin.android") version "1.8.10" apply false
} }