Skip to content

Commit 91b2d74

Browse files
authored
Merge pull request #131 from YAPP-Github/BOOK-245-fix/#124
fix: 시스템 권한 팝업에서 허용 시 카메라 프리뷰 안보이는 문제 수정
2 parents 99b14d8 + 5684370 commit 91b2d74

File tree

1 file changed

+58
-38
lines changed
  • feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr

1 file changed

+58
-38
lines changed

feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ import androidx.compose.material3.Text
3434
import androidx.compose.runtime.Composable
3535
import androidx.compose.runtime.DisposableEffect
3636
import androidx.compose.runtime.LaunchedEffect
37+
import androidx.compose.runtime.getValue
38+
import androidx.compose.runtime.mutableStateOf
3739
import androidx.compose.runtime.remember
40+
import androidx.compose.runtime.setValue
3841
import androidx.compose.ui.Alignment
3942
import androidx.compose.ui.Modifier
4043
import androidx.compose.ui.graphics.Color
@@ -89,11 +92,19 @@ private fun CameraPreview(
8992
val lifecycleOwner = LocalLifecycleOwner.current
9093
val permission = android.Manifest.permission.CAMERA
9194

92-
// UI에서 항상 권한 최신 상태 확인
93-
val isGranted = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
94-
val launcher = rememberLauncherForActivityResult(
95+
/**
96+
* Camera Permission Request
97+
*/
98+
var isGranted by remember {
99+
mutableStateOf(
100+
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED,
101+
)
102+
}
103+
val permissionLauncher = rememberLauncherForActivityResult(
95104
contract = ActivityResultContracts.RequestPermission(),
96105
) { granted ->
106+
isGranted = granted
107+
97108
if (!granted) {
98109
state.eventSink(OcrUiEvent.OnShowPermissionDialog)
99110
}
@@ -102,45 +113,20 @@ private fun CameraPreview(
102113
contract = ActivityResultContracts.StartActivityForResult(),
103114
) { _ -> }
104115

105-
val cameraController = remember { LifecycleCameraController(context) }
106-
val imageAnalyzer = remember {
107-
ImageAnalysis.Analyzer { imageProxy ->
108-
state.eventSink(OcrUiEvent.OnFrameReceived(imageProxy))
109-
}
110-
}
111-
112-
val systemUiController = rememberSystemUiController()
113-
114-
DisposableEffect(systemUiController) {
115-
systemUiController.setSystemBarsColor(
116-
color = Color.Transparent,
117-
darkIcons = false,
118-
isNavigationBarContrastEnforced = false,
119-
)
120-
121-
onDispose {
122-
systemUiController.setSystemBarsColor(
123-
color = Color.Transparent,
124-
darkIcons = true,
125-
isNavigationBarContrastEnforced = false,
126-
)
127-
}
128-
}
129-
130116
// 최초 진입 시 권한 요청
131117
LaunchedEffect(Unit) {
132118
if (!isGranted) {
133119
state.eventSink(OcrUiEvent.OnHidePermissionDialog)
134-
launcher.launch(permission)
120+
permissionLauncher.launch(permission)
135121
}
136122
}
137123

138-
// 앱이 포그라운드로 북귀할 때 OS 권한 체크
124+
// 앱이 포그라운드로 북귀할 때 OS 권한 동기화
139125
DisposableEffect(Unit) {
140126
val observer = LifecycleEventObserver { _, event ->
141127
if (event == Lifecycle.Event.ON_RESUME) {
142-
val currentGrant = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
143-
if (currentGrant) {
128+
isGranted = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
129+
if (isGranted) {
144130
state.eventSink(OcrUiEvent.OnHidePermissionDialog)
145131
} else {
146132
state.eventSink(OcrUiEvent.OnShowPermissionDialog)
@@ -151,18 +137,52 @@ private fun CameraPreview(
151137
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
152138
}
153139

154-
DisposableEffect(lifecycleOwner, cameraController) {
155-
cameraController.bindToLifecycle(lifecycleOwner)
156-
cameraController.setImageAnalysisAnalyzer(
157-
ContextCompat.getMainExecutor(context),
158-
imageAnalyzer,
159-
)
140+
/**
141+
* Camera Controller & ImageAnalyzer
142+
*/
143+
val cameraController = remember { LifecycleCameraController(context) }
144+
val imageAnalyzer = remember {
145+
ImageAnalysis.Analyzer { imageProxy ->
146+
state.eventSink(OcrUiEvent.OnFrameReceived(imageProxy))
147+
}
148+
}
149+
150+
DisposableEffect(isGranted, lifecycleOwner, cameraController) {
151+
if (isGranted) {
152+
cameraController.bindToLifecycle(lifecycleOwner)
153+
cameraController.setImageAnalysisAnalyzer(
154+
ContextCompat.getMainExecutor(context),
155+
imageAnalyzer,
156+
)
157+
}
158+
160159
onDispose {
161160
cameraController.unbind()
162161
cameraController.clearImageAnalysisAnalyzer()
163162
}
164163
}
165164

165+
/**
166+
* SystemStatusBar Color
167+
*/
168+
val systemUiController = rememberSystemUiController()
169+
170+
DisposableEffect(systemUiController) {
171+
systemUiController.setSystemBarsColor(
172+
color = Color.Transparent,
173+
darkIcons = false,
174+
isNavigationBarContrastEnforced = false,
175+
)
176+
177+
onDispose {
178+
systemUiController.setSystemBarsColor(
179+
color = Color.Transparent,
180+
darkIcons = true,
181+
isNavigationBarContrastEnforced = false,
182+
)
183+
}
184+
}
185+
166186
ReedScaffold(
167187
modifier = modifier.fillMaxSize(),
168188
containerColor = Neutral950,

0 commit comments

Comments
 (0)