Skip to content

Commit

Permalink
Fixes for autofill / focus lifecycle handling, added Paparazzi snapsh…
Browse files Browse the repository at this point in the history
…ot test (#4)
  • Loading branch information
hbmartin authored Mar 21, 2023
1 parent ae3c095 commit 0153435
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 55 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ jobs:
run: ./gradlew :ccp:detekt
- name: Lint
run: ./gradlew :ccp:lint
- name: Paparazzi snapshot test
run: ./gradlew :ccp:verifyPaparazziDebug
- name: Build with Gradle
run: ./gradlew build
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@
* 🇺🇳 Automatic country recognition (detection by sim card if sim card is inserted)
* ⚙️ Advanced customization options (see usage below)
* 🏁 Fast! Flattened layouts and immutable collections prevent unwanted recomposition.
* ✅ Code quality checks with Ktlint and Detekt, snapshot testing with Paparazzi
* 🗣 Multilingual:
* Turkish
* English
* Italian
* Arabic
* Russian
* Dutch
* Spanish
* Somali
* French
* Chinese
* Turkish
* English
* Italian
* Arabic
* Russian
* Dutch
* Spanish
* Somali
* French
* Chinese

## Screenshots

Expand Down
3 changes: 0 additions & 3 deletions app/src/main/java/com/togitech/togii/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
Expand All @@ -30,7 +28,6 @@ import androidx.compose.ui.unit.dp
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.togitech.ccp.component.TogiCountryCodePicker
import com.togitech.togii.ui.theme.TogiiTheme
import kotlinx.collections.immutable.persistentSetOf

class MainActivity : ComponentActivity() {

Expand Down
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ buildscript {
ext {
activity_compose_version = '1.7.0-beta02'
compose_compiler_version = '1.4.3'
compose_version = '1.4.0-beta02'
compose_tooling_version = '1.3.3'
compose_version = '1.4.0-rc01'
core_ktx_version = '1.9.0'
lifecycle_version = '2.6.0-rc01'
material3_version = '1.1.0-alpha07'
Expand Down
7 changes: 4 additions & 3 deletions ccp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id 'maven-publish'
id "io.gitlab.arturbosch.detekt" version "1.22.0"
id 'org.jetbrains.dokka'
id 'app.cash.paparazzi' version '1.2.0'
}

group 'com.togitech'
Expand Down Expand Up @@ -59,9 +60,9 @@ dependencies {
implementation "androidx.activity:activity-compose:$activity_compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
api 'com.googlecode.libphonenumber:libphonenumber:8.13.7'
implementation "androidx.compose.ui:ui-tooling-preview:$compose_tooling_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_tooling_version"
api 'com.googlecode.libphonenumber:libphonenumber:8.13.8'
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"

detektPlugins("ru.kode:detekt-rules-compose:1.2.2")
detektPlugins("com.twitter.compose.rules:detekt:0.0.26")
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.togitech.ccp.component

import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
Expand All @@ -14,7 +15,6 @@ import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -98,11 +98,13 @@ fun TogiCountryCodePicker(
OutlinedTextField(
modifier = modifier
.fillMaxWidth()
.focusRequester(focusRequester = focusRequester)
.autofill(
autofillTypes = listOf(AutofillType.PhoneNumberNational),
onFill = { phoneNumber = it },
focusRequester = focusRequester,
)
.focusRequester(focusRequester = focusRequester),
.focusable(),
shape = shape,
value = phoneNumber,
onValueChange = {
Expand Down Expand Up @@ -171,10 +173,6 @@ fun TogiCountryCodePicker(
}
},
)

LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
}

@Composable
Expand All @@ -195,14 +193,16 @@ private fun PlaceholderNumberHint(
@OptIn(ExperimentalComposeUiApi::class)
fun Modifier.autofill(
autofillTypes: List<AutofillType>,
onFill: ((String) -> Unit),
) = composed {
onFill: (String) -> Unit,
focusRequester: FocusRequester,
) = this then composed {
val autofill = LocalAutofill.current
val autofillNode = AutofillNode(onFill = onFill, autofillTypes = autofillTypes)
LocalAutofillTree.current += autofillNode

this.onGloballyPositioned {
autofillNode.boundingBox = it.boundsInWindow()
focusRequester.requestFocus()
}.onFocusChanged { focusState ->
autofill?.run {
if (focusState.isFocused) {
Expand Down
68 changes: 68 additions & 0 deletions ccp/src/test/java/com/togitech/ccp/CountryCodePickTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.togitech.ccp

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import app.cash.paparazzi.DeviceConfig.Companion.PIXEL_5
import app.cash.paparazzi.Paparazzi
import com.togitech.ccp.component.TogiCountryCodePicker
import org.junit.Rule
import org.junit.Test

class CountryCodePickTest {
@get:Rule
val paparazzi = Paparazzi(
deviceConfig = PIXEL_5,
theme = "android:Theme.Material.Light.NoActionBar",
)

@Test
fun test() {
paparazzi.snapshot {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
val phoneNumber = rememberSaveable { mutableStateOf("") }
val fullPhoneNumber = rememberSaveable { mutableStateOf("") }
var isNumberValid: Boolean by rememberSaveable { mutableStateOf(false) }

TogiCountryCodePicker(
text = "text",
onValueChange = { (code, phone), isValid ->
phoneNumber.value = phone
fullPhoneNumber.value = code + phone
isNumberValid = isValid
},
)
Spacer(modifier = Modifier.height(10.dp))

Text(
text = "Full Phone Number: ${fullPhoneNumber.value}",
color = if (!isNumberValid) Color.Red else Color.Green,
)

Text(
text = "Only Phone Number: ${phoneNumber.value}",
color = if (!isNumberValid) Color.Red else Color.Green,
)
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
18 changes: 14 additions & 4 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand All @@ -80,10 +80,10 @@ do
esac
done

APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
Expand Down Expand Up @@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -205,6 +209,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"

# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi

# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
Expand Down

0 comments on commit 0153435

Please sign in to comment.