@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Column
1313import androidx.compose.foundation.layout.Row
1414import androidx.compose.foundation.layout.Spacer
1515import androidx.compose.foundation.layout.WindowInsets
16+ import androidx.compose.foundation.layout.fillMaxHeight
1617import androidx.compose.foundation.layout.fillMaxSize
1718import androidx.compose.foundation.layout.height
1819import androidx.compose.foundation.layout.imePadding
@@ -21,22 +22,18 @@ import androidx.compose.foundation.layout.padding
2122import androidx.compose.foundation.layout.size
2223import androidx.compose.foundation.layout.width
2324import androidx.compose.foundation.layout.windowInsetsPadding
24- import androidx.compose.foundation.layout.wrapContentWidth
2525import androidx.compose.foundation.shape.ZeroCornerSize
2626import androidx.compose.foundation.text.BasicTextField
2727import androidx.compose.foundation.text.KeyboardActions
2828import androidx.compose.foundation.text.KeyboardOptions
2929import androidx.compose.material.Text
30- import androidx.compose.material.TextField
31- import androidx.compose.material.TextFieldDefaults
3230import androidx.compose.runtime.Composable
3331import androidx.compose.runtime.LaunchedEffect
3432import androidx.compose.runtime.collectAsState
3533import androidx.compose.runtime.getValue
3634import androidx.compose.runtime.remember
3735import androidx.compose.runtime.rememberCoroutineScope
3836import androidx.compose.ui.Alignment
39- import androidx.compose.ui.Alignment.Companion.BottomCenter
4037import androidx.compose.ui.Alignment.Companion.Center
4138import androidx.compose.ui.Alignment.Companion.CenterStart
4239import androidx.compose.ui.Alignment.Companion.CenterVertically
@@ -52,11 +49,11 @@ import androidx.compose.ui.platform.LocalFocusManager
5249import androidx.compose.ui.res.painterResource
5350import androidx.compose.ui.res.stringResource
5451import androidx.compose.ui.text.input.KeyboardType
52+ import androidx.compose.ui.text.input.TextFieldValue
5553import androidx.compose.ui.text.style.TextAlign
5654import androidx.compose.ui.tooling.preview.Preview
5755import androidx.compose.ui.unit.dp
5856import androidx.compose.ui.unit.sp
59- import androidx.constraintlayout.compose.ConstraintLayout
6057import androidx.hilt.navigation.compose.hiltViewModel
6158import com.getcode.R
6259import com.getcode.navigation.core.LocalCodeNavigator
@@ -66,7 +63,7 @@ import com.getcode.theme.CodeTheme
6663import com.getcode.theme.White05
6764import com.getcode.theme.White50
6865import com.getcode.theme.extraSmall
69- import com.getcode.util.debugBounds
66+ import com.getcode.util.PhoneUtils
7067import com.getcode.util.getActivity
7168import com.getcode.util.rememberedClickable
7269import com.getcode.view.components.ButtonState
@@ -75,7 +72,6 @@ import com.google.android.gms.auth.api.identity.GetPhoneNumberHintIntentRequest
7572import com.google.android.gms.auth.api.identity.Identity
7673import kotlinx.coroutines.delay
7774import kotlinx.coroutines.launch
78- import timber.log.Timber
7975
8076@Preview
8177@Composable
@@ -88,7 +84,6 @@ internal fun PhoneVerify(
8884 val dataState by viewModel.uiFlow.collectAsState()
8985 val focusRequester = remember { FocusRequester () }
9086 val context = LocalContext .current
91- val composeScope = rememberCoroutineScope()
9287 val focusManager = LocalFocusManager .current
9388
9489 Column (
@@ -105,101 +100,21 @@ internal fun PhoneVerify(
105100 horizontalAlignment = Alignment .CenterHorizontally ,
106101 verticalArrangement = Arrangement .spacedBy(CodeTheme .dimens.inset),
107102 ) {
108- Row (
103+ PhoneEntry (
109104 modifier = Modifier
110- .height(CodeTheme .dimens.grid.x12)
111- .border(
112- width = CodeTheme .dimens.border,
113- color = BrandLight ,
114- shape = CodeTheme .shapes.extraSmall
115- )
116- .background(White05 )
117- ) {
118- Row (
119- modifier = Modifier
120- .height(CodeTheme .dimens.grid.x12)
121- .clip(
122- CodeTheme .shapes.extraSmall
123- .copy(bottomEnd = ZeroCornerSize , topEnd = ZeroCornerSize )
124- )
125- .rememberedClickable {
126- composeScope.launch {
127- focusManager.clearFocus(true )
128- delay(500 )
129- openCountrySelector()
130- }
131- },
132- ) {
133- dataState.countryLocale.resId?.let { resId ->
134- Image (
135- modifier = Modifier
136- .align(CenterVertically )
137- .padding(start = CodeTheme .dimens.grid.x3)
138- .size(CodeTheme .dimens.staticGrid.x5)
139- .clip(CodeTheme .shapes.large),
140- painter = painterResource(resId),
141- contentDescription = " " ,
142- )
143- }
144- Box (
145- modifier = Modifier
146- .height(CodeTheme .dimens.grid.x12)
147- .align(CenterVertically )
148- .padding(horizontal = CodeTheme .dimens.grid.x3,),
149- contentAlignment = Center
150- ) {
151- Text (
152- style = CodeTheme .typography.subtitle1,
153- text = " +${dataState.countryLocale.phoneCode} "
154- )
155- }
156- }
157- Spacer (
158- modifier = Modifier
159- .background(BrandLight )
160- .width(1 .dp)
161- .height(CodeTheme .dimens.grid.x12)
162- )
163- BasicTextField (
164- modifier = Modifier
165- .wrapContentWidth()
166- .weight(1f )
167- .focusRequester(focusRequester),
168- value = dataState.phoneNumberFormattedTextFieldValue,
169- textStyle = CodeTheme .typography.subtitle1.copy(color = CodeTheme .colors.onBackground),
170- keyboardOptions = KeyboardOptions .Default .copy(keyboardType = KeyboardType .Phone ),
171- cursorBrush = SolidColor (Color .White ),
172- singleLine = true ,
173- keyboardActions = KeyboardActions (
174- onDone = {
175- viewModel.onSubmit(navigator, context.getActivity())
176- }
177- ),
178- onValueChange = {
179- if (! dataState.isLoading) {
180- viewModel.setPhoneInput(it.text, it.selection)
181- }
182- },
183- enabled = ! dataState.isLoading && ! dataState.isSuccess,
184- ) { textField ->
185- Box (
186- modifier = Modifier
187- .fillMaxSize()
188- .padding(start = CodeTheme .dimens.staticGrid.x2),
189- contentAlignment = CenterStart
190- ) {
191- if (dataState.phoneNumberFormattedTextFieldValue.text.isEmpty()) {
192- Text (
193- text = stringResource(id = R .string.title_phoneNumber),
194- color = White50 ,
195- fontSize = 20 .sp
196- )
197- }
198- textField()
199- }
200- }
201-
202- }
105+ .height(CodeTheme .dimens.grid.x12),
106+ focusManager = focusManager,
107+ focusRequester = focusRequester,
108+ locale = dataState.countryLocale,
109+ isLoading = dataState.isLoading,
110+ isSuccess = dataState.isSuccess,
111+ value = dataState.phoneNumberFormattedTextFieldValue,
112+ onValueChanged = {
113+ viewModel.setPhoneInput(it.text, it.selection)
114+ },
115+ openCountrySelector = openCountrySelector,
116+ onSubmit = { viewModel.onSubmit(navigator, context.getActivity()) }
117+ )
203118
204119 Text (
205120 modifier = Modifier .padding(horizontal = CodeTheme .dimens.grid.x2),
@@ -262,4 +177,111 @@ internal fun PhoneVerify(
262177 }
263178 }
264179 }
180+ }
181+
182+ @Composable
183+ private fun PhoneEntry (
184+ modifier : Modifier = Modifier ,
185+ focusManager : FocusManager ,
186+ focusRequester : FocusRequester ,
187+ locale : PhoneUtils .CountryLocale ,
188+ isLoading : Boolean ,
189+ isSuccess : Boolean ,
190+ value : TextFieldValue ,
191+ onValueChanged : (TextFieldValue ) -> Unit ,
192+ openCountrySelector : () -> Unit ,
193+ onSubmit : () -> Unit ,
194+ ) {
195+ val composeScope = rememberCoroutineScope()
196+ Row (
197+ modifier = modifier
198+ .border(
199+ width = CodeTheme .dimens.border,
200+ color = BrandLight ,
201+ shape = CodeTheme .shapes.extraSmall
202+ )
203+ .background(White05 )
204+ ) {
205+ Row (
206+ modifier = Modifier
207+ .height(CodeTheme .dimens.grid.x12)
208+ .clip(
209+ CodeTheme .shapes.extraSmall
210+ .copy(bottomEnd = ZeroCornerSize , topEnd = ZeroCornerSize )
211+ )
212+ .rememberedClickable {
213+ composeScope.launch {
214+ focusManager.clearFocus(true )
215+ delay(500 )
216+ openCountrySelector()
217+ }
218+ },
219+ ) {
220+ locale.resId?.let { resId ->
221+ Image (
222+ modifier = Modifier
223+ .align(CenterVertically )
224+ .padding(start = CodeTheme .dimens.grid.x3)
225+ .size(CodeTheme .dimens.staticGrid.x5)
226+ .clip(CodeTheme .shapes.large),
227+ painter = painterResource(resId),
228+ contentDescription = " " ,
229+ )
230+ }
231+ Box (
232+ modifier = Modifier
233+ .fillMaxHeight()
234+ .padding(vertical = CodeTheme .dimens.border)
235+ .padding(horizontal = CodeTheme .dimens.grid.x3,),
236+ contentAlignment = Center
237+ ) {
238+ Text (
239+ style = CodeTheme .typography.subtitle1,
240+ text = " +${locale.phoneCode} "
241+ )
242+ }
243+ }
244+ Spacer (
245+ modifier = Modifier
246+ .background(BrandLight )
247+ .width(1 .dp)
248+ .fillMaxHeight()
249+ )
250+ BasicTextField (
251+ modifier = Modifier
252+ .fillMaxHeight()
253+ .padding(top = CodeTheme .dimens.border)
254+ .weight(1f )
255+ .focusRequester(focusRequester),
256+ value = value,
257+ textStyle = CodeTheme .typography.subtitle1.copy(color = CodeTheme .colors.onBackground),
258+ keyboardOptions = KeyboardOptions .Default .copy(keyboardType = KeyboardType .Phone ),
259+ cursorBrush = SolidColor (Color .White ),
260+ singleLine = true ,
261+ keyboardActions = KeyboardActions (onDone = { onSubmit() }),
262+ onValueChange = {
263+ if (! isLoading) {
264+ onValueChanged(it)
265+ }
266+ },
267+ enabled = ! isLoading && ! isSuccess,
268+ ) { textField ->
269+ Box (
270+ modifier = Modifier
271+ .fillMaxSize()
272+ .padding(start = CodeTheme .dimens.staticGrid.x2),
273+ contentAlignment = CenterStart
274+ ) {
275+ if (value.text.isEmpty()) {
276+ Text (
277+ text = stringResource(id = R .string.title_phoneNumber),
278+ color = White50 ,
279+ fontSize = 20 .sp
280+ )
281+ }
282+ textField()
283+ }
284+ }
285+
286+ }
265287}
0 commit comments