@@ -27,6 +27,8 @@ import androidx.compose.foundation.layout.padding
27
27
import androidx.compose.foundation.layout.width
28
28
import androidx.compose.foundation.rememberScrollState
29
29
import androidx.compose.foundation.shape.RoundedCornerShape
30
+ import androidx.compose.foundation.text.KeyboardActions
31
+ import androidx.compose.foundation.text.KeyboardOptions
30
32
import androidx.compose.foundation.verticalScroll
31
33
import androidx.compose.material3.ExperimentalMaterial3Api
32
34
import androidx.compose.material3.Text
@@ -36,13 +38,15 @@ import androidx.compose.runtime.getValue
36
38
import androidx.compose.runtime.mutableStateOf
37
39
import androidx.compose.runtime.remember
38
40
import androidx.compose.runtime.rememberCoroutineScope
39
- import androidx.compose.runtime.setValue
40
41
import androidx.compose.ui.Alignment
41
42
import androidx.compose.ui.Modifier
42
43
import androidx.compose.ui.draw.clip
44
+ import androidx.compose.ui.focus.FocusRequester
45
+ import androidx.compose.ui.focus.focusRequester
43
46
import androidx.compose.ui.layout.ContentScale
44
47
import androidx.compose.ui.platform.LocalContext
45
48
import androidx.compose.ui.res.painterResource
49
+ import androidx.compose.ui.text.input.ImeAction
46
50
import androidx.compose.ui.text.style.TextAlign
47
51
import androidx.compose.ui.tooling.preview.Preview
48
52
import androidx.compose.ui.unit.dp
@@ -70,6 +74,7 @@ import com.record.upload.component.bottomsheet.DefinedContentBottomSheet
70
74
import com.record.upload.component.bottomsheet.SelectedVideoBottomSheet
71
75
import com.record.upload.extension.GalleryVideo
72
76
import com.record.upload.extension.getAllVideos
77
+ import kotlinx.coroutines.android.awaitFrame
73
78
import kotlinx.coroutines.flow.collectLatest
74
79
import kotlinx.coroutines.launch
75
80
import timber.log.Timber
@@ -84,6 +89,8 @@ fun VideoPickerRoute(
84
89
val state by viewModel.uiState.collectAsStateWithLifecycle()
85
90
val context = LocalContext .current
86
91
val coroutineScope = rememberCoroutineScope()
92
+ val locationFocusRequester = remember { FocusRequester () }
93
+ val contentFocusRequester = remember { FocusRequester () }
87
94
88
95
BackHandler (true ) {
89
96
coroutineScope.launch {
@@ -93,13 +100,21 @@ fun VideoPickerRoute(
93
100
94
101
LaunchedEffectWithLifecycle {
95
102
viewModel.getPresignedUrl()
96
- viewModel.sideEffect.collectLatest { }
97
103
}
98
104
99
105
LaunchedEffectWithLifecycle {
100
106
viewModel.sideEffect.collectLatest { sideEffect ->
101
107
when (sideEffect) {
102
108
is UploadSideEffect .PopBackStack -> popBackStack()
109
+ is UploadSideEffect .FocusLocation -> {
110
+ awaitFrame()
111
+ locationFocusRequester.requestFocus()
112
+ }
113
+
114
+ is UploadSideEffect .FocusContent -> {
115
+ awaitFrame()
116
+ contentFocusRequester.requestFocus()
117
+ }
103
118
}
104
119
}
105
120
}
@@ -119,6 +134,10 @@ fun VideoPickerRoute(
119
134
viewModel.uploadVideoToS3Bucket(context, it)
120
135
},
121
136
onClickBackStack = viewModel::popBackStack,
137
+ updateLocationTextField = viewModel::updateLocationTextField,
138
+ updateContentTextField = viewModel::updateContentTextField,
139
+ locationFocusRequester = locationFocusRequester,
140
+ contentFocusRequester = locationFocusRequester,
122
141
)
123
142
}
124
143
@@ -142,6 +161,10 @@ fun VideoPickerScreen(
142
161
onClickContentChip : (String ) -> Unit ,
143
162
setVideo : (GalleryVideo ) -> Unit ,
144
163
uploadVideoS3Bucket : (File ) -> Unit ,
164
+ updateContentTextField : (String ) -> Unit = {},
165
+ updateLocationTextField : (String ) -> Unit = {},
166
+ locationFocusRequester : FocusRequester = remember { FocusRequester () },
167
+ contentFocusRequester : FocusRequester = remember { FocusRequester () },
145
168
) {
146
169
val context = LocalContext .current
147
170
val cameraPermissionState = rememberPermissionState(
@@ -165,9 +188,6 @@ fun VideoPickerScreen(
165
188
) == PackageManager .PERMISSION_GRANTED ,
166
189
)
167
190
}
168
- var normalValue by remember {
169
- mutableStateOf(" " )
170
- }
171
191
val scope = rememberCoroutineScope()
172
192
val imageLoader = ImageLoader .Builder (context)
173
193
.components {
@@ -322,12 +342,14 @@ fun VideoPickerScreen(
322
342
)
323
343
RecordyBasicTextField (
324
344
modifier = Modifier
325
- .padding(horizontal = 16 .dp),
345
+ .padding(horizontal = 16 .dp)
346
+ .focusRequester(locationFocusRequester),
326
347
placeholder = " 영상 속 위치는 어디인가요?" ,
327
348
maxLines = 1 ,
328
349
maxLength = 10 ,
329
- value = normalValue,
330
- onValueChange = { normalValue = it },
350
+ value = state.locationTextValue,
351
+ onValueChange = updateLocationTextField,
352
+ keyboardOptions = KeyboardOptions .Default .copy(imeAction = ImeAction .Done ),
331
353
)
332
354
Text (
333
355
text = " 내용" ,
@@ -342,11 +364,15 @@ fun VideoPickerScreen(
342
364
maxLines = 20 ,
343
365
maxLength = 300 ,
344
366
minHeight = 148 .dp,
345
- value = normalValue ,
367
+ value = state.contentTextValue ,
346
368
modifier = Modifier
347
369
.padding(horizontal = 16 .dp)
348
- .padding(bottom = 10 .dp),
349
- onValueChange = { normalValue = it },
370
+ .padding(bottom = 10 .dp)
371
+ .focusRequester(contentFocusRequester),
372
+ onValueChange = updateContentTextField,
373
+ keyboardOptions = KeyboardOptions .Default .copy(
374
+ imeAction = ImeAction .Done
375
+ )
350
376
)
351
377
Box (modifier = Modifier .padding(16 .dp)) {
352
378
RecordyButton (
0 commit comments