Skip to content

Commit 25b490b

Browse files
committed
✨ Add generic settings panel
1 parent 0426939 commit 25b490b

File tree

10 files changed

+319
-100
lines changed

10 files changed

+319
-100
lines changed

app/src/main/java/co/stonephone/stonecamera/StoneCameraApp.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// StoneCameraApp.kt
2+
@file:kotlin.OptIn(ExperimentalMaterial3Api::class)
3+
24
package co.stonephone.stonecamera
35

46
import android.annotation.SuppressLint
@@ -10,6 +12,12 @@ import androidx.camera.lifecycle.ProcessCameraProvider
1012
import androidx.compose.foundation.background
1113
import androidx.compose.foundation.clickable
1214
import androidx.compose.foundation.layout.*
15+
import androidx.compose.foundation.shape.CircleShape
16+
import androidx.compose.material.icons.Icons
17+
import androidx.compose.material.icons.filled.FlipCameraAndroid
18+
import androidx.compose.material3.ExperimentalMaterial3Api
19+
import androidx.compose.material3.Icon
20+
import androidx.compose.material3.IconButton
1321
import androidx.compose.material3.MaterialTheme
1422
import androidx.compose.material3.Text
1523
import androidx.compose.runtime.*
@@ -27,6 +35,7 @@ import co.stonephone.stonecamera.plugins.PhotoModePlugin
2735
import co.stonephone.stonecamera.plugins.PinchToZoomPlugin
2836
import co.stonephone.stonecamera.plugins.QRScannerPlugin
2937
import co.stonephone.stonecamera.plugins.SettingLocation
38+
import co.stonephone.stonecamera.plugins.SettingsTrayPlugin
3039
import co.stonephone.stonecamera.plugins.ShutterFlashPlugin
3140
import co.stonephone.stonecamera.plugins.TapToFocusPlugin
3241
import co.stonephone.stonecamera.plugins.VolumeControlsPlugin
@@ -53,10 +62,13 @@ val PLUGINS = listOf(
5362
VolumeControlsPlugin(),
5463
PhotoModePlugin(),
5564
VideoModePlugin(),
65+
SettingsTrayPlugin()
5666
// DebugPlugin()
5767
)
5868

59-
@OptIn(ExperimentalCamera2Interop::class)
69+
@OptIn(
70+
ExperimentalCamera2Interop::class
71+
)
6072
@SuppressLint("ClickableViewAccessibility")
6173
@Composable
6274
fun StoneCameraApp(
@@ -141,8 +153,13 @@ fun StoneCameraApp(
141153
.align(Alignment.BottomCenter),
142154
verticalArrangement = Arrangement.SpaceBetween
143155
) {
144-
plugins.map {
145-
it.renderTray(stoneCameraViewModel, it)
156+
157+
Box(
158+
modifier = Modifier.fillMaxWidth(),
159+
) {
160+
plugins.map {
161+
it.renderTray(stoneCameraViewModel, it)
162+
}
146163
}
147164

148165
// Translucent overlay for mode switch & shutter
@@ -179,5 +196,6 @@ fun StoneCameraApp(
179196
}
180197
}
181198
}
199+
182200
}
183201
}

app/src/main/java/co/stonephone/stonecamera/plugins/AspectRatio.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package co.stonephone.stonecamera.plugins
22

3-
import android.app.Application
43
import android.util.Size
54
import androidx.camera.core.AspectRatio
65
import androidx.camera.core.ImageCapture
@@ -14,7 +13,6 @@ import androidx.compose.material3.MaterialTheme
1413
import androidx.compose.material3.Text
1514
import androidx.compose.ui.Modifier
1615
import androidx.compose.ui.graphics.Color
17-
import androidx.compose.ui.platform.LocalContext
1816
import androidx.compose.ui.text.font.FontWeight
1917
import androidx.compose.ui.unit.dp
2018
import co.stonephone.stonecamera.MyApplication
@@ -175,10 +173,10 @@ class AspectRatioPlugin : IPlugin {
175173
key = "aspectRatio",
176174
defaultValue = "16:9",
177175
options = listOf("16:9", "4:3", "FULL"),
178-
render = { value ->
176+
render = { value, isSelected ->
179177
Text(
180178
text = value,
181-
color = Color.White,
179+
color = if (isSelected) Color(0xFFFFCC00) else Color.White,
182180
style = MaterialTheme.typography.bodyLarge,
183181
fontWeight = FontWeight.Bold,
184182
modifier = Modifier
@@ -193,9 +191,9 @@ class AspectRatioPlugin : IPlugin {
193191
previewView!!.scaleType = PreviewView.ScaleType.FIT_CENTER
194192
}
195193
viewModel.recreateUseCases()
196-
197194
},
198-
renderLocation = SettingLocation.TOP
195+
renderLocation = SettingLocation.TOP,
196+
label = "Aspect Ratio"
199197
)
200198
)
201199
}

app/src/main/java/co/stonephone/stonecamera/plugins/Debug.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class DebugPlugin : IPlugin {
5151
x = visibleRegion!!.left.dp,
5252
y = visibleRegion!!.top.dp
5353
)
54-
.border(2.dp, Color.Yellow)
54+
.border(2.dp, Color(0xAAFFCC00))
5555
.padding(16.dp),
5656
contentAlignment = Alignment.TopCenter
5757
) { }

app/src/main/java/co/stonephone/stonecamera/plugins/Flash.kt

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ package co.stonephone.stonecamera.plugins
22

33
import android.util.Log
44
import androidx.camera.core.ImageCapture
5+
import androidx.compose.foundation.layout.Box
6+
import androidx.compose.foundation.layout.padding
57
import androidx.compose.material.icons.Icons
68
import androidx.compose.material.icons.filled.FlashAuto
79
import androidx.compose.material.icons.filled.FlashOff
810
import androidx.compose.material.icons.filled.FlashOn
911
import androidx.compose.material3.Icon
12+
import androidx.compose.material3.IconButton
13+
import androidx.compose.ui.Modifier
1014
import androidx.compose.ui.graphics.Color
15+
import androidx.compose.ui.unit.dp
1116
import co.stonephone.stonecamera.StoneCameraViewModel
1217

1318
class FlashPlugin : IPlugin {
@@ -19,8 +24,7 @@ class FlashPlugin : IPlugin {
1924
}
2025

2126
override fun onImageCapture(
22-
viewModel: StoneCameraViewModel,
23-
imageCapture: ImageCapture.Builder
27+
viewModel: StoneCameraViewModel, imageCapture: ImageCapture.Builder
2428
): ImageCapture.Builder {
2529
val flashMode = viewModel.getSetting<String>("flash") ?: "OFF"
2630
val mode = flashModeStringToMode(flashMode)
@@ -40,33 +44,37 @@ class FlashPlugin : IPlugin {
4044
}
4145
}
4246

43-
override val settings = { viewModel: StoneCameraViewModel ->
47+
override val settings: (StoneCameraViewModel) -> List<PluginSetting> = { viewModel ->
4448
listOf(
4549
PluginSetting.EnumSetting(
4650
key = "flash",
51+
label = "Flash",
4752
defaultValue = "OFF",
4853
options = listOf("OFF", "ON", "AUTO"),
49-
render = { flashMode ->
50-
Icon(
51-
imageVector = when (flashMode) {
52-
"OFF" -> Icons.Default.FlashOff // Replace with your preferred icon
53-
"ON" -> Icons.Default.FlashOn
54-
"AUTO" -> Icons.Default.FlashAuto // You may need to add custom icons for Flash Auto
55-
else -> {
56-
Icons.Default.FlashOff
57-
}
58-
},
59-
contentDescription = when (flashMode) {
60-
"OFF" -> "Flash Off"
61-
"ON" -> "Flash On"
62-
"AUTO" -> "Flash Auto"
63-
else -> {
64-
"Flash"
65-
}
66-
},
67-
tint = Color.White // Customize as needed
68-
)
69-
54+
render = { flashMode, isSelected ->
55+
Box(
56+
modifier = Modifier.padding(8.dp)
57+
) {
58+
Icon(
59+
imageVector = when (flashMode) {
60+
"OFF" -> Icons.Default.FlashOff // Replace with your preferred icon
61+
"ON" -> Icons.Default.FlashOn
62+
"AUTO" -> Icons.Default.FlashAuto // You may need to add custom icons for Flash Auto
63+
else -> {
64+
Icons.Default.FlashOff
65+
}
66+
},
67+
contentDescription = when (flashMode) {
68+
"OFF" -> "Flash Off"
69+
"ON" -> "Flash On"
70+
"AUTO" -> "Flash Auto"
71+
else -> {
72+
"Flash"
73+
}
74+
},
75+
tint = if (isSelected) Color(0xFFFFCC00) else Color.White
76+
)
77+
}
7078
},
7179
onChange = { viewModel, value ->
7280
viewModel.recreateUseCases()

app/src/main/java/co/stonephone/stonecamera/plugins/IPlugin.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package co.stonephone.stonecamera.plugins
22

33
import android.content.ContentValues
44
import android.media.Image
5-
import androidx.camera.core.ImageAnalysis
65
import androidx.camera.core.ImageCapture
76
import androidx.camera.core.ImageProxy
87
import androidx.camera.core.Preview
@@ -115,20 +114,23 @@ enum class SettingLocation {
115114
sealed class PluginSetting(
116115
val key: String,
117116
val defaultValue: Any?,
117+
val label: String,
118118
val onChange: (StoneCameraViewModel, Any?) -> Unit,
119119
val renderLocation: SettingLocation? = SettingLocation.NONE,
120120
) {
121121

122122
class EnumSetting(
123123
key: String,
124124
defaultValue: String,
125+
label: String,
125126
renderLocation: SettingLocation? = SettingLocation.NONE,
126127
val options: List<String>,
127-
val render: @Composable (value: String) -> Unit,
128+
val render: @Composable (value: String, Boolean) -> Unit,
128129
onChange: (StoneCameraViewModel, String) -> Unit
129130
) : PluginSetting(
130131
key,
131132
defaultValue,
133+
label,
132134
onChange as (StoneCameraViewModel, Any?) -> Unit,
133135
renderLocation
134136
)
@@ -137,22 +139,25 @@ sealed class PluginSetting(
137139
key: String,
138140
defaultValue: Float,
139141
renderLocation: SettingLocation? = SettingLocation.NONE,
142+
label: String,
140143
val minValue: Float,
141144
val maxValue: Float,
142145
val stepValue: Float? = null,
143146
onChange: (StoneCameraViewModel, Float) -> Unit
144147
) : PluginSetting(
145148
key,
146149
defaultValue,
150+
label,
147151
onChange as (StoneCameraViewModel, Any?) -> Unit,
148152
renderLocation
149153
)
150154

151155
class CustomSetting(
152156
key: String,
153157
defaultValue: String,
158+
label: String,
154159
renderLocation: SettingLocation? = SettingLocation.NONE,
155160
val customRender: @Composable (StoneCameraViewModel, Any?, (Any?) -> Unit) -> Unit, // Render function with a callback for value changes
156161
onChange: (StoneCameraViewModel, Any?) -> Unit
157-
) : PluginSetting(key, defaultValue, onChange, renderLocation)
162+
) : PluginSetting(key, defaultValue, label, onChange, renderLocation)
158163
}

0 commit comments

Comments
 (0)