mirror of
https://github.com/AU-COVIDSafe/mobile-android.git
synced 2025-01-18 16:56:34 +00:00
COVIDSafe code from version 1.0.28 (#4)
This commit is contained in:
parent
05a2ca94a6
commit
c16533add6
35 changed files with 1653 additions and 413 deletions
|
@ -40,8 +40,8 @@ android {
|
||||||
Before you increase the targetSdkVersion make sure that all its usage are still working
|
Before you increase the targetSdkVersion make sure that all its usage are still working
|
||||||
*/
|
*/
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 21
|
versionCode 28
|
||||||
versionName "1.0.21"
|
versionName "1.0.28"
|
||||||
buildConfigField "String", "GITHASH", "\"${getGitHash()}\""
|
buildConfigField "String", "GITHASH", "\"${getGitHash()}\""
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
@ -243,6 +243,10 @@ dependencies {
|
||||||
implementation "androidx.lifecycle:lifecycle-service:2.2.0"
|
implementation "androidx.lifecycle:lifecycle-service:2.2.0"
|
||||||
implementation 'com.github.razir.progressbutton:progressbutton:2.0.1'
|
implementation 'com.github.razir.progressbutton:progressbutton:2.0.1'
|
||||||
|
|
||||||
|
// flags
|
||||||
|
implementation 'com.michaelfotiadis:android-country-flags:1.0.3'
|
||||||
|
|
||||||
androidTestImplementation "androidx.room:room-testing:2.2.5"
|
androidTestImplementation "androidx.room:room-testing:2.2.5"
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="au.gov.health.covidsafe">
|
package="au.gov.health.covidsafe">
|
||||||
|
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.bluetooth_le"
|
android:name="android.hardware.bluetooth_le"
|
||||||
android:required="true" />
|
android:required="true" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
|
||||||
|
@ -19,13 +20,14 @@
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="au.gov.health.covidsafe.TracerApp"
|
android:name="au.gov.health.covidsafe.TracerApp"
|
||||||
|
tools:replace="android:supportsRtl"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/MyTheme.DayNight"
|
android:theme="@style/MyTheme.DayNight">
|
||||||
android:networkSecurityConfig="@xml/network_security_config">
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="au.gov.health.covidsafe.SplashActivity"
|
android:name="au.gov.health.covidsafe.SplashActivity"
|
||||||
|
@ -38,16 +40,21 @@
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name="au.gov.health.covidsafe.ui.onboarding.OnboardingActivity"
|
android:name="au.gov.health.covidsafe.ui.onboarding.OnboardingActivity"
|
||||||
android:windowSoftInputMode="adjustPan"
|
android:screenOrientation="portrait"
|
||||||
android:screenOrientation="portrait" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="au.gov.health.covidsafe.ui.onboarding.CountryCodeSelectionActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="au.gov.health.covidsafe.WebViewActivity"
|
android:name="au.gov.health.covidsafe.WebViewActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<activity
|
<activity
|
||||||
android:name="au.gov.health.covidsafe.HomeActivity"
|
android:name="au.gov.health.covidsafe.HomeActivity"
|
||||||
android:windowSoftInputMode="adjustPan"
|
android:screenOrientation="portrait"
|
||||||
android:screenOrientation="portrait" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
|
|
||||||
<receiver android:name="au.gov.health.covidsafe.boot.StartOnBootReceiver">
|
<receiver android:name="au.gov.health.covidsafe.boot.StartOnBootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -9,6 +9,12 @@ import au.gov.health.covidsafe.security.crypto.AESEncryptionForPreAndroidM
|
||||||
object Preference {
|
object Preference {
|
||||||
private const val PREF_ID = "Tracer_pref"
|
private const val PREF_ID = "Tracer_pref"
|
||||||
private const val IS_ONBOARDED = "IS_ONBOARDED"
|
private const val IS_ONBOARDED = "IS_ONBOARDED"
|
||||||
|
private const val CALLING_CODE = "CALLING_CODE"
|
||||||
|
private const val AUSTRALIA_CALLING_CODE = 61
|
||||||
|
private const val COUNTRY_NAME_RES_ID = "COUNTRY_NAME"
|
||||||
|
private const val AUSTRALIA_COUNTRY_NAME_RES_ID = R.string.country_au
|
||||||
|
private const val NATIONAL_FLAG_RES_ID = "NATIONAL_FLAG_RES_ID"
|
||||||
|
private const val AUSTRALIA_NATIONAL_FLAG_RES_ID = R.drawable.ic_list_country_au
|
||||||
private const val PHONE_NUMBER = "PHONE_NUMBER"
|
private const val PHONE_NUMBER = "PHONE_NUMBER"
|
||||||
private const val HANDSHAKE_PIN = "HANDSHAKE_PIN"
|
private const val HANDSHAKE_PIN = "HANDSHAKE_PIN"
|
||||||
private const val DEVICE_ID = "DEVICE_ID"
|
private const val DEVICE_ID = "DEVICE_ID"
|
||||||
|
@ -41,7 +47,7 @@ object Preference {
|
||||||
.edit().putString(AES_IV, value)?.apply()
|
.edit().putString(AES_IV, value)?.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEncodedAESInitialisationVector(context: Context) : String? {
|
fun getEncodedAESInitialisationVector(context: Context): String? {
|
||||||
return context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
return context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
.getString(AES_IV, null)
|
.getString(AES_IV, null)
|
||||||
}
|
}
|
||||||
|
@ -119,6 +125,43 @@ object Preference {
|
||||||
.edit().putString(PHONE_NUMBER, value).apply()
|
.edit().putString(PHONE_NUMBER, value).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPhoneNumber(context: Context): String {
|
||||||
|
return context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
?.getString(PHONE_NUMBER, "") ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putCallingCode(context: Context, value: Int) {
|
||||||
|
context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
.edit().putInt(CALLING_CODE, value).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCallingCode(context: Context): Int {
|
||||||
|
return context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
?.getInt(CALLING_CODE, AUSTRALIA_CALLING_CODE) ?: AUSTRALIA_CALLING_CODE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putCountryNameResID(context: Context, value: Int) {
|
||||||
|
context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
.edit().putInt(COUNTRY_NAME_RES_ID, value).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCountryNameResID(context: Context): Int {
|
||||||
|
return context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
?.getInt(COUNTRY_NAME_RES_ID, AUSTRALIA_COUNTRY_NAME_RES_ID)
|
||||||
|
?: AUSTRALIA_COUNTRY_NAME_RES_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putNationalFlagResID(context: Context, value: Int) {
|
||||||
|
context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
.edit().putInt(NATIONAL_FLAG_RES_ID, value).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNationalFlagResID(context: Context): Int {
|
||||||
|
return context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
|
?.getInt(NATIONAL_FLAG_RES_ID, AUSTRALIA_NATIONAL_FLAG_RES_ID)
|
||||||
|
?: AUSTRALIA_NATIONAL_FLAG_RES_ID
|
||||||
|
}
|
||||||
|
|
||||||
fun putNextFetchTimeInMillis(context: Context, time: Long) {
|
fun putNextFetchTimeInMillis(context: Context, time: Long) {
|
||||||
context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
context.getSharedPreferences(PREF_ID, Context.MODE_PRIVATE)
|
||||||
.edit().putLong(NEXT_FETCH_TIME, time).apply()
|
.edit().putLong(NEXT_FETCH_TIME, time).apply()
|
||||||
|
|
|
@ -7,14 +7,15 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
|
import android.provider.Settings
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import au.gov.health.covidsafe.R
|
||||||
|
import au.gov.health.covidsafe.Utils
|
||||||
import pub.devrel.easypermissions.AppSettingsDialog
|
import pub.devrel.easypermissions.AppSettingsDialog
|
||||||
import pub.devrel.easypermissions.EasyPermissions
|
import pub.devrel.easypermissions.EasyPermissions
|
||||||
import pub.devrel.easypermissions.PermissionRequest
|
import pub.devrel.easypermissions.PermissionRequest
|
||||||
import au.gov.health.covidsafe.R
|
|
||||||
import au.gov.health.covidsafe.Utils
|
|
||||||
|
|
||||||
const val REQUEST_ENABLE_BT = 123
|
const val REQUEST_ENABLE_BT = 123
|
||||||
const val LOCATION = 345
|
const val LOCATION = 345
|
||||||
|
@ -85,6 +86,22 @@ fun Fragment.excludeFromBatteryOptimization(onEndCallback: (() -> Unit)? = null)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Fragment.gotoPushNotificationSettings() {
|
||||||
|
val context = requireContext()
|
||||||
|
val intent = Intent()
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||||
|
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
|
||||||
|
intent.putExtra("app_package", context.packageName)
|
||||||
|
intent.putExtra("app_uid", context.applicationInfo.uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
fun Fragment.isBlueToothEnabled(): Boolean? {
|
fun Fragment.isBlueToothEnabled(): Boolean? {
|
||||||
val bluetoothManager = activity?.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?
|
val bluetoothManager = activity?.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?
|
||||||
return bluetoothManager?.adapter?.isEnabled
|
return bluetoothManager?.adapter?.isEnabled
|
||||||
|
|
|
@ -17,7 +17,9 @@ class GetOnboardingOtp(private val awsClient: AwsClient, lifecycle: Lifecycle) :
|
||||||
override suspend fun run(params: GetOtpParams): Either<Exception, OTPChallengeResponse> {
|
override suspend fun run(params: GetOtpParams): Either<Exception, OTPChallengeResponse> {
|
||||||
return try {
|
return try {
|
||||||
val response = awsClient.initiateAuth(
|
val response = awsClient.initiateAuth(
|
||||||
OTPChallengeRequest(params.phoneNumber,
|
OTPChallengeRequest(
|
||||||
|
params.countryCode,
|
||||||
|
params.phoneNumber,
|
||||||
params.deviceId,
|
params.deviceId,
|
||||||
params.postCode,
|
params.postCode,
|
||||||
params.age,
|
params.age,
|
||||||
|
@ -48,11 +50,14 @@ class GetOnboardingOtp(private val awsClient: AwsClient, lifecycle: Lifecycle) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class GetOtpParams(internal val phoneNumber: String,
|
data class GetOtpParams(
|
||||||
|
internal val countryCode: String,
|
||||||
|
internal val phoneNumber: String,
|
||||||
internal val deviceId: String,
|
internal val deviceId: String,
|
||||||
internal val postCode: String?,
|
internal val postCode: String?,
|
||||||
internal val age: String?,
|
internal val age: String?,
|
||||||
internal val name: String?)
|
internal val name: String?
|
||||||
|
)
|
||||||
|
|
||||||
sealed class GetOnboardingOtpException : Exception() {
|
sealed class GetOnboardingOtpException : Exception() {
|
||||||
class GetOtpServiceException(val code: Int? = null) : GetOnboardingOtpException()
|
class GetOtpServiceException(val code: Int? = null) : GetOnboardingOtpException()
|
||||||
|
|
|
@ -3,8 +3,11 @@ package au.gov.health.covidsafe.networking.request
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
data class OTPChallengeRequest(val phone_number: String,
|
data class OTPChallengeRequest(
|
||||||
|
val country_code: String,
|
||||||
|
val phone_number: String,
|
||||||
val device_id: String,
|
val device_id: String,
|
||||||
val postcode: String?,
|
val postcode: String?,
|
||||||
val age: String?,
|
val age: String?,
|
||||||
val name: String?)
|
val name: String?
|
||||||
|
)
|
|
@ -3,8 +3,9 @@ package au.gov.health.covidsafe.streetpass
|
||||||
import android.bluetooth.BluetoothDevice
|
import android.bluetooth.BluetoothDevice
|
||||||
import android.bluetooth.BluetoothGatt
|
import android.bluetooth.BluetoothGatt
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.gson.Gson
|
import android.os.Build
|
||||||
import au.gov.health.covidsafe.logging.CentralLog
|
import au.gov.health.covidsafe.logging.CentralLog
|
||||||
|
import com.google.gson.Gson
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
class Work constructor(
|
class Work constructor(
|
||||||
|
@ -16,7 +17,7 @@ class Work constructor(
|
||||||
var checklist = WorkCheckList()
|
var checklist = WorkCheckList()
|
||||||
var gatt: BluetoothGatt? = null
|
var gatt: BluetoothGatt? = null
|
||||||
var finished = false
|
var finished = false
|
||||||
var timeout : Long = 0
|
var timeout: Long = 0
|
||||||
|
|
||||||
private val TAG = "Work"
|
private val TAG = "Work"
|
||||||
|
|
||||||
|
@ -36,7 +37,12 @@ class Work constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
gattCallback: StreetPassWorker.StreetPassGattCallback
|
gattCallback: StreetPassWorker.StreetPassGattCallback
|
||||||
) {
|
) {
|
||||||
gatt = device.connectGatt(context, false, gattCallback)
|
gatt = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
device.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE)
|
||||||
|
} else {
|
||||||
|
device.connectGatt(context, false, gattCallback)
|
||||||
|
}
|
||||||
|
|
||||||
if (gatt == null) {
|
if (gatt == null) {
|
||||||
CentralLog.e(TAG, "Unable to connect to ${device.address}")
|
CentralLog.e(TAG, "Unable to connect to ${device.address}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,6 @@ object Encryption {
|
||||||
|
|
||||||
private val NONCE_PADDING = ByteArray(14) { 0x0E.toByte() }
|
private val NONCE_PADDING = ByteArray(14) { 0x0E.toByte() }
|
||||||
private val serverPubKey: PublicKey = readKey()
|
private val serverPubKey: PublicKey = readKey()
|
||||||
private val symCipher: Cipher = makeSymCipher()
|
|
||||||
|
|
||||||
private var cachedEphPubKey: ByteArray? = null
|
private var cachedEphPubKey: ByteArray? = null
|
||||||
private var cachedAesKey: SecretKey? = null
|
private var cachedAesKey: SecretKey? = null
|
||||||
|
@ -131,6 +130,7 @@ object Encryption {
|
||||||
// IV = AES(ctr, iv=null), AES(plaintext, iv=IV) === AES(ctr_with_padding || plaintext, iv=null)
|
// IV = AES(ctr, iv=null), AES(plaintext, iv=IV) === AES(ctr_with_padding || plaintext, iv=null)
|
||||||
// Using the latter construction to reduce key expansions
|
// Using the latter construction to reduce key expansions
|
||||||
val ivParams = IvParameterSpec(ByteArray(16)) // null IV
|
val ivParams = IvParameterSpec(ByteArray(16)) // null IV
|
||||||
|
val symCipher: Cipher = makeSymCipher()
|
||||||
symCipher.init(Cipher.ENCRYPT_MODE, keys.aesKey, ivParams)
|
symCipher.init(Cipher.ENCRYPT_MODE, keys.aesKey, ivParams)
|
||||||
val ciphertextWithIV: ByteArray = symCipher.doFinal(keys.nonce.plus(NONCE_PADDING).plus(data))
|
val ciphertextWithIV: ByteArray = symCipher.doFinal(keys.nonce.plus(NONCE_PADDING).plus(data))
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,8 @@ class HomeFragment : BaseFragment(), EasyPermissions.PermissionCallbacks {
|
||||||
bluetooth_card_view.setOnClickListener { requestBlueToothPermissionThenNextPermission() }
|
bluetooth_card_view.setOnClickListener { requestBlueToothPermissionThenNextPermission() }
|
||||||
location_card_view.setOnClickListener { askForLocationPermission() }
|
location_card_view.setOnClickListener { askForLocationPermission() }
|
||||||
battery_card_view.setOnClickListener { excludeFromBatteryOptimization() }
|
battery_card_view.setOnClickListener { excludeFromBatteryOptimization() }
|
||||||
|
push_card_view.setOnClickListener { gotoPushNotificationSettings() }
|
||||||
|
|
||||||
home_been_tested_button.setOnClickListener {
|
home_been_tested_button.setOnClickListener {
|
||||||
navigateTo(R.id.action_home_to_selfIsolate)
|
navigateTo(R.id.action_home_to_selfIsolate)
|
||||||
}
|
}
|
||||||
|
@ -264,7 +266,11 @@ class HomeFragment : BaseFragment(), EasyPermissions.PermissionCallbacks {
|
||||||
private fun updatePushNotificationStatus() {
|
private fun updatePushNotificationStatus() {
|
||||||
isPushNotificationEnabled()?.let {
|
isPushNotificationEnabled()?.let {
|
||||||
push_card_view.visibility = VISIBLE
|
push_card_view.visibility = VISIBLE
|
||||||
push_card_view.render(formatPushNotificationTitle(it), it)
|
push_card_view.render(
|
||||||
|
formatPushNotificationTitle(it),
|
||||||
|
it,
|
||||||
|
getString(R.string.home_app_permission_push_notification_prompt)
|
||||||
|
)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
push_card_view.visibility = GONE
|
push_card_view.visibility = GONE
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,12 @@ import android.content.Context
|
||||||
import android.content.res.TypedArray
|
import android.content.res.TypedArray
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import au.gov.health.covidsafe.R
|
import au.gov.health.covidsafe.R
|
||||||
|
import au.gov.health.covidsafe.TracerApp
|
||||||
import kotlinx.android.synthetic.main.view_card_permission_card.view.*
|
import kotlinx.android.synthetic.main.view_card_permission_card.view.*
|
||||||
|
|
||||||
class PermissionStatusCard @JvmOverloads constructor(
|
class PermissionStatusCard @JvmOverloads constructor(
|
||||||
|
@ -28,10 +31,20 @@ class PermissionStatusCard @JvmOverloads constructor(
|
||||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height)
|
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(text: String, correct: Boolean) {
|
fun render(title: String, correct: Boolean, body: String? = null) {
|
||||||
|
val errorTextColor = ContextCompat.getColor(TracerApp.AppContext, R.color.error)
|
||||||
|
val normalTextColor = ContextCompat.getColor(TracerApp.AppContext, R.color.slack_black)
|
||||||
|
|
||||||
permission_icon.isSelected = correct
|
permission_icon.isSelected = correct
|
||||||
permission_title.text = text
|
permission_title.text = title
|
||||||
|
permission_title.setTextColor(if (correct) normalTextColor else errorTextColor)
|
||||||
|
|
||||||
|
if (correct || body == null) {
|
||||||
|
permission_body.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
permission_body.visibility = View.VISIBLE
|
||||||
|
permission_body.text = body
|
||||||
|
permission_body.setTextColor(if (correct) normalTextColor else errorTextColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
package au.gov.health.covidsafe.ui.onboarding
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.speech.RecognizerIntent
|
||||||
|
import android.speech.RecognizerIntent.EXTRA_RESULTS
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import au.gov.health.covidsafe.R
|
||||||
|
import kotlinx.android.synthetic.main.activity_country_code_selection.*
|
||||||
|
|
||||||
|
fun RecyclerView.smoothSnapToPosition(
|
||||||
|
position: Int,
|
||||||
|
snapMode: Int = LinearSmoothScroller.SNAP_TO_START
|
||||||
|
) {
|
||||||
|
val smoothScroller = object : LinearSmoothScroller(this.context) {
|
||||||
|
override fun getVerticalSnapPreference(): Int = snapMode
|
||||||
|
override fun getHorizontalSnapPreference(): Int = snapMode
|
||||||
|
}
|
||||||
|
|
||||||
|
smoothScroller.targetPosition = position
|
||||||
|
layoutManager?.startSmoothScroll(smoothScroller)
|
||||||
|
}
|
||||||
|
|
||||||
|
const val VOICE_TO_TEXT_REQUEST_CODE = 2020
|
||||||
|
|
||||||
|
class CountryCodeSelectionActivity : Activity() {
|
||||||
|
val countryListItem = CountryList.getCountryList()
|
||||||
|
|
||||||
|
private fun setupToolbar() {
|
||||||
|
countrySelectionToolbar.setNavigationOnClickListener {
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
countrySelectionToolbar.title = getString(R.string.select_country_or_region)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupCountryListRecyclerView() {
|
||||||
|
val linearLayoutManager = LinearLayoutManager(this)
|
||||||
|
countryListRecyclerView.layoutManager = linearLayoutManager
|
||||||
|
|
||||||
|
val dividerItemDecoration = DividerItemDecoration(
|
||||||
|
this,
|
||||||
|
linearLayoutManager.orientation
|
||||||
|
)
|
||||||
|
countryListRecyclerView.addItemDecoration(dividerItemDecoration)
|
||||||
|
|
||||||
|
countryListRecyclerView.adapter = CountryListRecyclerViewAdapter(
|
||||||
|
this,
|
||||||
|
countryListItem
|
||||||
|
) {
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun countryListScrollToPosition(positionOfLetter: Int) {
|
||||||
|
countryListRecyclerView.scrollToPosition(positionOfLetter)
|
||||||
|
|
||||||
|
Thread {
|
||||||
|
Thread.sleep(100)
|
||||||
|
runOnUiThread {
|
||||||
|
countryListRecyclerView.smoothSnapToPosition(positionOfLetter)
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupSearchFunctions() {
|
||||||
|
// text based search
|
||||||
|
countryRegionNameEditText.setOnFocusChangeListener { _, hasFocus ->
|
||||||
|
countrySearchImageView.visibility = if (hasFocus) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
countryRegionNameEditText.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
fun getPositionOfCountryName(searchText: String): Int {
|
||||||
|
countryListItem.forEachIndexed { index, countryListItemInterface ->
|
||||||
|
if (countryListItemInterface is CountryGroupTitle) {
|
||||||
|
val groupTitle = getString(countryListItemInterface.titleResId)
|
||||||
|
if (groupTitle.startsWith(searchText, ignoreCase = true)
|
||||||
|
) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
} else if (countryListItemInterface is CountryListItem) {
|
||||||
|
val countryName = getString(countryListItemInterface.countryNameResId)
|
||||||
|
if (countryName.contains(searchText, ignoreCase = true)
|
||||||
|
) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
val callingCode = countryListItemInterface.callingCode
|
||||||
|
if ("$callingCode".startsWith(searchText, ignoreCase = true)
|
||||||
|
) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
s?.toString()?.let { enteredText ->
|
||||||
|
val positionOfCountryName = getPositionOfCountryName(enteredText)
|
||||||
|
if (positionOfCountryName != -1) {
|
||||||
|
countryListScrollToPosition(positionOfCountryName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// voice to text search
|
||||||
|
microphoneImageView.setOnClickListener {
|
||||||
|
startActivityForResult(
|
||||||
|
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH),
|
||||||
|
VOICE_TO_TEXT_REQUEST_CODE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupInitialLetterRecyclerView() {
|
||||||
|
val alphabet = ArrayList<String>()
|
||||||
|
var letter = 'A'
|
||||||
|
while (letter <= 'Z') {
|
||||||
|
if (letter != 'W' && letter != 'X') {
|
||||||
|
alphabet.add(letter.toString())
|
||||||
|
}
|
||||||
|
++letter
|
||||||
|
}
|
||||||
|
|
||||||
|
countryInitialLetterRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||||
|
countryInitialLetterRecyclerView.adapter = CountryInitialLetterRecyclerViewAdapter(
|
||||||
|
this,
|
||||||
|
alphabet
|
||||||
|
) { letterClicked ->
|
||||||
|
fun getPositionOfLetter(letter: String): Int {
|
||||||
|
countryListItem.forEachIndexed { index, countryListItemInterface ->
|
||||||
|
if (countryListItemInterface is CountryGroupTitle) {
|
||||||
|
val groupTitle = getString(countryListItemInterface.titleResId)
|
||||||
|
if (groupTitle.startsWith(letter, ignoreCase = true)) {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val positionOfLetter = getPositionOfLetter(letterClicked)
|
||||||
|
|
||||||
|
countryListScrollToPosition(positionOfLetter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
|
||||||
|
if (requestCode == VOICE_TO_TEXT_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||||
|
data?.getStringArrayListExtra(EXTRA_RESULTS)?.let {
|
||||||
|
countryRegionNameEditText.setText(it.first())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_country_code_selection)
|
||||||
|
|
||||||
|
setupToolbar()
|
||||||
|
setupCountryListRecyclerView()
|
||||||
|
setupInitialLetterRecyclerView()
|
||||||
|
|
||||||
|
// set up the search functions
|
||||||
|
setupSearchFunctions()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package au.gov.health.covidsafe.ui.onboarding
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import au.gov.health.covidsafe.R
|
||||||
|
|
||||||
|
class CountryInitialLetterHolder(
|
||||||
|
itemView: View,
|
||||||
|
private val onLetterClicked: (letter: String) -> Unit
|
||||||
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
fun setLetter(letter: String) {
|
||||||
|
val letterTextView = itemView.findViewById<TextView>(R.id.country_initial_letter)
|
||||||
|
letterTextView.text = letter
|
||||||
|
letterTextView.setOnClickListener {
|
||||||
|
onLetterClicked(letter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CountryInitialLetterRecyclerViewAdapter(
|
||||||
|
private val context: Context,
|
||||||
|
private val initialLetters: List<String>,
|
||||||
|
private val onLetterClicked: (letter: String) -> Unit
|
||||||
|
) : RecyclerView.Adapter<CountryInitialLetterHolder>() {
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CountryInitialLetterHolder {
|
||||||
|
return CountryInitialLetterHolder(
|
||||||
|
LayoutInflater.from(context).inflate(
|
||||||
|
R.layout.view_list_item_country_initial_letter,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
onLetterClicked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return initialLetters.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CountryInitialLetterHolder, position: Int) {
|
||||||
|
holder.setLetter(initialLetters[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
package au.gov.health.covidsafe.ui.onboarding
|
||||||
|
|
||||||
|
import au.gov.health.covidsafe.R
|
||||||
|
|
||||||
|
object CountryList {
|
||||||
|
|
||||||
|
fun getCountryList() : List<CountryListItemInterface>{
|
||||||
|
// for now, it returns the grouping for English only, in the future, it should return
|
||||||
|
// different groupings according to different language
|
||||||
|
return groupingForEnglish
|
||||||
|
}
|
||||||
|
|
||||||
|
private val groupingForEnglish = listOf(
|
||||||
|
CountryGroupTitle(R.string.options_for_australia),
|
||||||
|
CountryListItem(R.string.country_au, 61, R.drawable.ic_list_country_au),
|
||||||
|
CountryListItem(R.string.country_nf, 672, R.drawable.ic_list_country_nf),
|
||||||
|
CountryGroupTitle(R.string.group_title_a),
|
||||||
|
// CountryListItem(R.string.country_af, 93, R.drawable.ic_list_country_af),
|
||||||
|
CountryListItem(R.string.country_al, 355, R.drawable.ic_list_country_al),
|
||||||
|
CountryListItem(R.string.country_dz, 213, R.drawable.ic_list_country_dz),
|
||||||
|
// CountryListItem(R.string.country_ad, 376, R.drawable.ic_list_country_ad),
|
||||||
|
CountryListItem(R.string.country_ao, 244, R.drawable.ic_list_country_ao),
|
||||||
|
CountryListItem(R.string.country_ai, 1, R.drawable.ic_list_country_ai),
|
||||||
|
CountryListItem(R.string.country_ag, 1, R.drawable.ic_list_country_ag),
|
||||||
|
CountryListItem(R.string.country_ar, 54, R.drawable.ic_list_country_ar),
|
||||||
|
CountryListItem(R.string.country_am, 374, R.drawable.ic_list_country_am),
|
||||||
|
CountryListItem(R.string.country_aw, 297, R.drawable.ic_list_country_aw),
|
||||||
|
CountryListItem(R.string.country_au, 61, R.drawable.ic_list_country_au),
|
||||||
|
CountryListItem(R.string.country_at, 43, R.drawable.ic_list_country_at),
|
||||||
|
CountryListItem(R.string.country_az, 994, R.drawable.ic_list_country_az),
|
||||||
|
CountryGroupTitle(R.string.group_title_b),
|
||||||
|
CountryListItem(R.string.country_bs, 1, R.drawable.ic_list_country_bs),
|
||||||
|
CountryListItem(R.string.country_bh, 973, R.drawable.ic_list_country_bh),
|
||||||
|
CountryListItem(R.string.country_bd, 880, R.drawable.ic_list_country_bd),
|
||||||
|
CountryListItem(R.string.country_bb, 1, R.drawable.ic_list_country_bb),
|
||||||
|
CountryListItem(R.string.country_by, 375, R.drawable.ic_list_country_by),
|
||||||
|
CountryListItem(R.string.country_be, 32, R.drawable.ic_list_country_be),
|
||||||
|
CountryListItem(R.string.country_bz, 501, R.drawable.ic_list_country_bz),
|
||||||
|
CountryListItem(R.string.country_bj, 229, R.drawable.ic_list_country_bj),
|
||||||
|
CountryListItem(R.string.country_bm, 1, R.drawable.ic_list_country_bm),
|
||||||
|
// CountryListItem(R.string.country_bt, 975, R.drawable.ic_list_country_bt),
|
||||||
|
CountryListItem(R.string.country_bo, 591, R.drawable.ic_list_country_bo),
|
||||||
|
CountryListItem(R.string.country_ba, 387, R.drawable.ic_list_country_ba),
|
||||||
|
CountryListItem(R.string.country_bw, 267, R.drawable.ic_list_country_bw),
|
||||||
|
CountryListItem(R.string.country_br, 55, R.drawable.ic_list_country_br),
|
||||||
|
// CountryListItem(R.string.country_bn, 673, R.drawable.ic_list_country_bn),
|
||||||
|
CountryListItem(R.string.country_vg, 1, R.drawable.ic_list_country_vg),
|
||||||
|
CountryListItem(R.string.country_bg, 359, R.drawable.ic_list_country_bg),
|
||||||
|
CountryListItem(R.string.country_bf, 226, R.drawable.ic_list_country_bf),
|
||||||
|
// CountryListItem(R.string.country_bi, 257, R.drawable.ic_list_country_bi),
|
||||||
|
CountryGroupTitle(R.string.group_title_c),
|
||||||
|
CountryListItem(R.string.country_kh, 855, R.drawable.ic_list_country_kh),
|
||||||
|
CountryListItem(R.string.country_cm, 237, R.drawable.ic_list_country_cm),
|
||||||
|
CountryListItem(R.string.country_ca, 1, R.drawable.ic_list_country_ca),
|
||||||
|
CountryListItem(R.string.country_cv, 238, R.drawable.ic_list_country_cv),
|
||||||
|
CountryListItem(R.string.country_ky, 1, R.drawable.ic_list_country_ky),
|
||||||
|
// CountryListItem(R.string.country_cf, 236, R.drawable.ic_list_country_cf),
|
||||||
|
// CountryListItem(R.string.country_td, 235, R.drawable.ic_list_country_td),
|
||||||
|
CountryListItem(R.string.country_cl, 56, R.drawable.ic_list_country_cl),
|
||||||
|
CountryListItem(R.string.country_cn, 86, R.drawable.ic_list_country_cn),
|
||||||
|
CountryListItem(R.string.country_co, 57, R.drawable.ic_list_country_co),
|
||||||
|
// CountryListItem(R.string.country_km, 269, R.drawable.ic_list_country_km),
|
||||||
|
// CountryListItem(R.string.country_ck, 682, R.drawable.ic_list_country_ck),
|
||||||
|
CountryListItem(R.string.country_cr, 506, R.drawable.ic_list_country_cr),
|
||||||
|
CountryListItem(R.string.country_hr, 385, R.drawable.ic_list_country_hr),
|
||||||
|
CountryListItem(R.string.country_cu, 53, R.drawable.ic_list_country_cu),
|
||||||
|
CountryListItem(R.string.country_cw, 599, R.drawable.ic_list_country_cw),
|
||||||
|
CountryListItem(R.string.country_cy, 357, R.drawable.ic_list_country_cy),
|
||||||
|
CountryListItem(R.string.country_cz, 420, R.drawable.ic_list_country_cz),
|
||||||
|
// CountryListItem(R.string.country_cd, 243, R.drawable.ic_list_country_cd),
|
||||||
|
CountryGroupTitle(R.string.group_title_d),
|
||||||
|
CountryListItem(R.string.country_dk, 45, R.drawable.ic_list_country_dk),
|
||||||
|
// CountryListItem(R.string.country_dj, 253, R.drawable.ic_list_country_dj),
|
||||||
|
CountryListItem(R.string.country_dm, 1, R.drawable.ic_list_country_dm),
|
||||||
|
CountryListItem(R.string.country_do, 1, R.drawable.ic_list_country_do),
|
||||||
|
CountryGroupTitle(R.string.group_title_e),
|
||||||
|
CountryListItem(R.string.country_ec, 593, R.drawable.ic_list_country_ec),
|
||||||
|
// CountryListItem(R.string.country_eg, 20, R.drawable.ic_list_country_eg),
|
||||||
|
CountryListItem(R.string.country_sv, 503, R.drawable.ic_list_country_sv),
|
||||||
|
// CountryListItem(R.string.country_gq, 240, R.drawable.ic_list_country_gq),
|
||||||
|
CountryListItem(R.string.country_ee, 372, R.drawable.ic_list_country_ee),
|
||||||
|
// CountryListItem(R.string.country_et, 251, R.drawable.ic_list_country_et),
|
||||||
|
CountryGroupTitle(R.string.group_title_f),
|
||||||
|
// CountryListItem(R.string.country_fo, 298, R.drawable.ic_list_country_fo),
|
||||||
|
CountryListItem(R.string.country_fj, 679, R.drawable.ic_list_country_fj),
|
||||||
|
CountryListItem(R.string.country_fi, 358, R.drawable.ic_list_country_fi),
|
||||||
|
CountryListItem(R.string.country_fr, 33, R.drawable.ic_list_country_fr),
|
||||||
|
CountryGroupTitle(R.string.group_title_g),
|
||||||
|
// CountryListItem(R.string.country_gf, 995, R.drawable.ic_list_country_fr),
|
||||||
|
CountryListItem(R.string.country_ga, 241, R.drawable.ic_list_country_ga),
|
||||||
|
// CountryListItem(R.string.country_gm, 220, R.drawable.ic_list_country_gm),
|
||||||
|
CountryListItem(R.string.country_ge, 995, R.drawable.ic_list_country_ge),
|
||||||
|
CountryListItem(R.string.country_de, 49, R.drawable.ic_list_country_de),
|
||||||
|
CountryListItem(R.string.country_gh, 233, R.drawable.ic_list_country_gh),
|
||||||
|
// CountryListItem(R.string.country_gi, 350, R.drawable.ic_list_country_gi),
|
||||||
|
CountryListItem(R.string.country_gr, 30, R.drawable.ic_list_country_gr),
|
||||||
|
// CountryListItem(R.string.country_gl, 299, R.drawable.ic_list_country_gl),
|
||||||
|
CountryListItem(R.string.country_gd, 1, R.drawable.ic_list_country_gd),
|
||||||
|
// CountryListItem(R.string.country_gp, 224, R.drawable.ic_list_country_fr),
|
||||||
|
CountryListItem(R.string.country_gu, 1, R.drawable.ic_list_country_gu),
|
||||||
|
CountryListItem(R.string.country_gt, 502, R.drawable.ic_list_country_gt),
|
||||||
|
// CountryListItem(R.string.country_gn, 224, R.drawable.ic_list_country_gn),
|
||||||
|
CountryListItem(R.string.country_gw, 245, R.drawable.ic_list_country_gw),
|
||||||
|
// CountryListItem(R.string.country_gy, 592, R.drawable.ic_list_country_gy),
|
||||||
|
CountryGroupTitle(R.string.group_title_h),
|
||||||
|
CountryListItem(R.string.country_ht, 509, R.drawable.ic_list_country_ht),
|
||||||
|
CountryListItem(R.string.country_hn, 504, R.drawable.ic_list_country_hn),
|
||||||
|
CountryListItem(R.string.country_hk, 852, R.drawable.ic_list_country_hk),
|
||||||
|
CountryListItem(R.string.country_hu, 36, R.drawable.ic_list_country_hu),
|
||||||
|
CountryGroupTitle(R.string.group_title_i),
|
||||||
|
CountryListItem(R.string.country_is, 354, R.drawable.ic_list_country_is),
|
||||||
|
CountryListItem(R.string.country_in, 91, R.drawable.ic_list_country_in),
|
||||||
|
CountryListItem(R.string.country_id, 62, R.drawable.ic_list_country_id),
|
||||||
|
CountryListItem(R.string.country_ir, 964, R.drawable.ic_list_country_ir),
|
||||||
|
CountryListItem(R.string.country_iq, 964, R.drawable.ic_list_country_iq),
|
||||||
|
CountryListItem(R.string.country_ie, 353, R.drawable.ic_list_country_ie),
|
||||||
|
CountryListItem(R.string.country_il, 972, R.drawable.ic_list_country_il),
|
||||||
|
// CountryListItem(R.string.country_it, 39, R.drawable.ic_list_country_it),
|
||||||
|
CountryListItem(R.string.country_ci, 225, R.drawable.ic_list_country_ci),
|
||||||
|
CountryGroupTitle(R.string.group_title_j),
|
||||||
|
CountryListItem(R.string.country_jm, 1, R.drawable.ic_list_country_jm),
|
||||||
|
CountryListItem(R.string.country_jp, 81, R.drawable.ic_list_country_jp),
|
||||||
|
CountryListItem(R.string.country_jo, 962, R.drawable.ic_list_country_jo),
|
||||||
|
CountryGroupTitle(R.string.group_title_k),
|
||||||
|
CountryListItem(R.string.country_kz, 7, R.drawable.ic_list_country_kz),
|
||||||
|
CountryListItem(R.string.country_ke, 254, R.drawable.ic_list_country_ke),
|
||||||
|
// CountryListItem(R.string.country_ki, 686, R.drawable.ic_list_country_ki),
|
||||||
|
CountryListItem(R.string.country_kw, 965, R.drawable.ic_list_country_kw),
|
||||||
|
CountryListItem(R.string.country_kg, 996, R.drawable.ic_list_country_kg),
|
||||||
|
CountryGroupTitle(R.string.group_title_l),
|
||||||
|
CountryListItem(R.string.country_la, 856, R.drawable.ic_list_country_la),
|
||||||
|
CountryListItem(R.string.country_lv, 371, R.drawable.ic_list_country_lv),
|
||||||
|
CountryListItem(R.string.country_lb, 961, R.drawable.ic_list_country_lb),
|
||||||
|
// CountryListItem(R.string.country_ls, 266, R.drawable.ic_list_country_ls),
|
||||||
|
// CountryListItem(R.string.country_lr, 231, R.drawable.ic_list_country_lr),
|
||||||
|
// CountryListItem(R.string.country_ly, 218, R.drawable.ic_list_country_ly),
|
||||||
|
CountryListItem(R.string.country_li, 423, R.drawable.ic_list_country_li),
|
||||||
|
CountryListItem(R.string.country_lt, 370, R.drawable.ic_list_country_lt),
|
||||||
|
CountryListItem(R.string.country_lu, 352, R.drawable.ic_list_country_lu),
|
||||||
|
CountryGroupTitle(R.string.group_title_m),
|
||||||
|
CountryListItem(R.string.country_mo, 853, R.drawable.ic_list_country_mo),
|
||||||
|
// CountryListItem(R.string.country_mg, 261, R.drawable.ic_list_country_mg),
|
||||||
|
// CountryListItem(R.string.country_mw, 265, R.drawable.ic_list_country_mw),
|
||||||
|
CountryListItem(R.string.country_my, 60, R.drawable.ic_list_country_my),
|
||||||
|
// CountryListItem(R.string.country_mv, 960, R.drawable.ic_list_country_mv),
|
||||||
|
CountryListItem(R.string.country_ml, 223, R.drawable.ic_list_country_ml),
|
||||||
|
CountryListItem(R.string.country_mt, 356, R.drawable.ic_list_country_mt),
|
||||||
|
CountryListItem(R.string.country_mq, 1, R.drawable.ic_list_country_mq),
|
||||||
|
// CountryListItem(R.string.country_mr, 222, R.drawable.ic_list_country_mr),
|
||||||
|
CountryListItem(R.string.country_mu, 230, R.drawable.ic_list_country_mu),
|
||||||
|
CountryListItem(R.string.country_mx, 52, R.drawable.ic_list_country_mx),
|
||||||
|
CountryListItem(R.string.country_md, 373, R.drawable.ic_list_country_md),
|
||||||
|
// CountryListItem(R.string.country_mc, 377, R.drawable.ic_list_country_mc),
|
||||||
|
// CountryListItem(R.string.country_mn, 976, R.drawable.ic_list_country_mn),
|
||||||
|
// CountryListItem(R.string.country_me, 382, R.drawable.ic_list_country_me),
|
||||||
|
CountryListItem(R.string.country_ms, 1, R.drawable.ic_list_country_ms),
|
||||||
|
CountryListItem(R.string.country_ma, 212, R.drawable.ic_list_country_ma),
|
||||||
|
CountryListItem(R.string.country_mz, 258, R.drawable.ic_list_country_mz),
|
||||||
|
CountryListItem(R.string.country_mm, 95, R.drawable.ic_list_country_mm),
|
||||||
|
CountryGroupTitle(R.string.group_title_n),
|
||||||
|
CountryListItem(R.string.country_na, 264, R.drawable.ic_list_country_na),
|
||||||
|
CountryListItem(R.string.country_np, 977, R.drawable.ic_list_country_np),
|
||||||
|
CountryListItem(R.string.country_nl, 31, R.drawable.ic_list_country_nl),
|
||||||
|
// CountryListItem(R.string.country_an, 599, R.drawable.ic_list_country_an),
|
||||||
|
// CountryListItem(R.string.country_nc, 687, R.drawable.ic_list_country_nc),
|
||||||
|
CountryListItem(R.string.country_nz, 64, R.drawable.ic_list_country_nz),
|
||||||
|
CountryListItem(R.string.country_ni, 505, R.drawable.ic_list_country_ni),
|
||||||
|
CountryListItem(R.string.country_ne, 227, R.drawable.ic_list_country_ne),
|
||||||
|
CountryListItem(R.string.country_ng, 234, R.drawable.ic_list_country_ng),
|
||||||
|
CountryListItem(R.string.country_nf, 672, R.drawable.ic_list_country_nf),
|
||||||
|
CountryListItem(R.string.country_mk, 389, R.drawable.ic_list_country_mk),
|
||||||
|
CountryListItem(R.string.country_no, 47, R.drawable.ic_list_country_no),
|
||||||
|
CountryGroupTitle(R.string.group_title_o),
|
||||||
|
CountryListItem(R.string.country_om, 968, R.drawable.ic_list_country_om),
|
||||||
|
CountryGroupTitle(R.string.group_title_p),
|
||||||
|
CountryListItem(R.string.country_pk, 92, R.drawable.ic_list_country_pk),
|
||||||
|
// CountryListItem(R.string.country_pw, 680, R.drawable.ic_list_country_pw),
|
||||||
|
// CountryListItem(R.string.country_ps, 970, R.drawable.ic_list_country_ps),
|
||||||
|
CountryListItem(R.string.country_pa, 507, R.drawable.ic_list_country_pa),
|
||||||
|
CountryListItem(R.string.country_pg, 675, R.drawable.ic_list_country_pg),
|
||||||
|
CountryListItem(R.string.country_py, 595, R.drawable.ic_list_country_py),
|
||||||
|
CountryListItem(R.string.country_pe, 51, R.drawable.ic_list_country_pe),
|
||||||
|
CountryListItem(R.string.country_ph, 63, R.drawable.ic_list_country_ph),
|
||||||
|
CountryListItem(R.string.country_pl, 48, R.drawable.ic_list_country_pl),
|
||||||
|
CountryListItem(R.string.country_pt, 351, R.drawable.ic_list_country_pt),
|
||||||
|
CountryListItem(R.string.country_pr, 1, R.drawable.ic_list_country_pr),
|
||||||
|
CountryGroupTitle(R.string.group_title_q),
|
||||||
|
CountryListItem(R.string.country_qa, 974, R.drawable.ic_list_country_qa),
|
||||||
|
CountryGroupTitle(R.string.group_title_r),
|
||||||
|
// CountryListItem(R.string.country_cg, 242, R.drawable.ic_list_country_cg),
|
||||||
|
// CountryListItem(R.string.country_re, 262, R.drawable.ic_list_country_fr),
|
||||||
|
// CountryListItem(R.string.country_ro, 40, R.drawable.ic_list_country_ro),
|
||||||
|
CountryListItem(R.string.country_ru, 7, R.drawable.ic_list_country_ru),
|
||||||
|
CountryListItem(R.string.country_rw, 250, R.drawable.ic_list_country_rw),
|
||||||
|
CountryGroupTitle(R.string.group_title_s),
|
||||||
|
CountryListItem(R.string.country_kn, 1, R.drawable.ic_list_country_kn),
|
||||||
|
CountryListItem(R.string.country_lc, 1, R.drawable.ic_list_country_lc),
|
||||||
|
CountryListItem(R.string.country_vc, 1, R.drawable.ic_list_country_vc),
|
||||||
|
// CountryListItem(R.string.country_ws, 685, R.drawable.ic_list_country_ws),
|
||||||
|
// CountryListItem(R.string.country_st, 239, R.drawable.ic_list_country_st),
|
||||||
|
// CountryListItem(R.string.country_sa, 966, R.drawable.ic_list_country_sa),
|
||||||
|
CountryListItem(R.string.country_sn, 221, R.drawable.ic_list_country_sn),
|
||||||
|
CountryListItem(R.string.country_rs, 381, R.drawable.ic_list_country_rs),
|
||||||
|
// CountryListItem(R.string.country_sc, 248, R.drawable.ic_list_country_sc),
|
||||||
|
// CountryListItem(R.string.country_sl, 232, R.drawable.ic_list_country_sl),
|
||||||
|
CountryListItem(R.string.country_sg, 65, R.drawable.ic_list_country_sg),
|
||||||
|
CountryListItem(R.string.country_sk, 421, R.drawable.ic_list_country_sk),
|
||||||
|
CountryListItem(R.string.country_si, 386, R.drawable.ic_list_country_si),
|
||||||
|
CountryListItem(R.string.country_sb, 677, R.drawable.ic_list_country_sb),
|
||||||
|
// CountryListItem(R.string.country_so, 252, R.drawable.ic_list_country_so),
|
||||||
|
CountryListItem(R.string.country_za, 27, R.drawable.ic_list_country_za),
|
||||||
|
CountryListItem(R.string.country_kr, 82, R.drawable.ic_list_country_kr),
|
||||||
|
// CountryListItem(R.string.country_ss, 211, R.drawable.ic_list_country_ss),
|
||||||
|
CountryListItem(R.string.country_es, 34, R.drawable.ic_list_country_es),
|
||||||
|
CountryListItem(R.string.country_lk, 94, R.drawable.ic_list_country_lk),
|
||||||
|
CountryListItem(R.string.country_sd, 249, R.drawable.ic_list_country_sd),
|
||||||
|
// CountryListItem(R.string.country_sr, 597, R.drawable.ic_list_country_sr),
|
||||||
|
// CountryListItem(R.string.country_sz, 268, R.drawable.ic_list_country_sz),
|
||||||
|
CountryListItem(R.string.country_se, 46, R.drawable.ic_list_country_se),
|
||||||
|
CountryListItem(R.string.country_ch, 41, R.drawable.ic_list_country_ch),
|
||||||
|
CountryGroupTitle(R.string.group_title_t),
|
||||||
|
CountryListItem(R.string.country_tw, 886, R.drawable.ic_list_country_tw),
|
||||||
|
CountryListItem(R.string.country_tj, 992, R.drawable.ic_list_country_tj),
|
||||||
|
CountryListItem(R.string.country_tz, 255, R.drawable.ic_list_country_tz),
|
||||||
|
CountryListItem(R.string.country_th, 66, R.drawable.ic_list_country_th),
|
||||||
|
// CountryListItem(R.string.country_tl, 670, R.drawable.ic_list_country_tl),
|
||||||
|
CountryListItem(R.string.country_tg, 228, R.drawable.ic_list_country_tg),
|
||||||
|
// CountryListItem(R.string.country_to, 676, R.drawable.ic_list_country_to),
|
||||||
|
CountryListItem(R.string.country_tt, 1, R.drawable.ic_list_country_tt),
|
||||||
|
CountryListItem(R.string.country_tn, 216, R.drawable.ic_list_country_tn),
|
||||||
|
CountryListItem(R.string.country_tr, 90, R.drawable.ic_list_country_tr),
|
||||||
|
CountryListItem(R.string.country_tm, 993, R.drawable.ic_list_country_tm),
|
||||||
|
CountryListItem(R.string.country_tc, 1, R.drawable.ic_list_country_tc),
|
||||||
|
CountryGroupTitle(R.string.group_title_u),
|
||||||
|
CountryListItem(R.string.country_ug, 256, R.drawable.ic_list_country_ug),
|
||||||
|
CountryListItem(R.string.country_ua, 380, R.drawable.ic_list_country_ua),
|
||||||
|
CountryListItem(R.string.country_ae, 971, R.drawable.ic_list_country_ae),
|
||||||
|
CountryListItem(R.string.country_gb, 44, R.drawable.ic_list_country_gb),
|
||||||
|
CountryListItem(R.string.country_us, 1, R.drawable.ic_list_country_us),
|
||||||
|
CountryListItem(R.string.country_uy, 598, R.drawable.ic_list_country_uy),
|
||||||
|
CountryListItem(R.string.country_uz, 998, R.drawable.ic_list_country_uz),
|
||||||
|
CountryGroupTitle(R.string.group_title_v),
|
||||||
|
// CountryListItem(R.string.country_vu, 678, R.drawable.ic_list_country_vu),
|
||||||
|
CountryListItem(R.string.country_ve, 58, R.drawable.ic_list_country_ve),
|
||||||
|
CountryListItem(R.string.country_vn, 84, R.drawable.ic_list_country_vn),
|
||||||
|
CountryListItem(R.string.country_vi, 1, R.drawable.ic_list_country_vi),
|
||||||
|
CountryGroupTitle(R.string.group_title_y),
|
||||||
|
CountryListItem(R.string.country_ye, 967, R.drawable.ic_list_country_ye),
|
||||||
|
CountryGroupTitle(R.string.group_title_z),
|
||||||
|
CountryListItem(R.string.country_zm, 260, R.drawable.ic_list_country_zm),
|
||||||
|
CountryListItem(R.string.country_zw, 263, R.drawable.ic_list_country_zw)
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
package au.gov.health.covidsafe.ui.onboarding
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import au.gov.health.covidsafe.Preference
|
||||||
|
import au.gov.health.covidsafe.R
|
||||||
|
import au.gov.health.covidsafe.TracerApp
|
||||||
|
|
||||||
|
const val VIEW_TYPE_GROUP_TITLE = 1
|
||||||
|
const val VIEW_TYPE_COUNTRY = 2
|
||||||
|
|
||||||
|
interface CountryListItemInterface
|
||||||
|
|
||||||
|
class CountryListItem(
|
||||||
|
val countryNameResId: Int,
|
||||||
|
val callingCode: Int,
|
||||||
|
val flagResID: Int
|
||||||
|
) : CountryListItemInterface
|
||||||
|
|
||||||
|
class CountryGroupTitle(
|
||||||
|
val titleResId: Int
|
||||||
|
) : CountryListItemInterface
|
||||||
|
|
||||||
|
class CountryGroupTitleHolder(
|
||||||
|
itemView: View
|
||||||
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
fun setCountryGroupTitle(title: String) {
|
||||||
|
itemView.findViewById<TextView>(R.id.country_group_title).text = title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CountryListItemHolder(
|
||||||
|
itemView: View,
|
||||||
|
private val onCountryClicked: () -> Unit
|
||||||
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
private var countryNameResId: Int = 0
|
||||||
|
private var callingCode: Int = 0
|
||||||
|
private var flagResID: Int = 0
|
||||||
|
|
||||||
|
fun setCountryListItem(countryNameResId: Int,
|
||||||
|
countryName: String,
|
||||||
|
callingCode: Int,
|
||||||
|
flagResID: Int) {
|
||||||
|
this.countryNameResId = countryNameResId
|
||||||
|
this.callingCode = callingCode
|
||||||
|
this.flagResID = flagResID
|
||||||
|
|
||||||
|
itemView.findViewById<TextView>(R.id.country_list_name).text = countryName
|
||||||
|
itemView.findViewById<TextView>(R.id.country_list_calling_code).text = "+$callingCode"
|
||||||
|
itemView.findViewById<ImageView>(R.id.country_list_flag).setImageResource(flagResID)
|
||||||
|
|
||||||
|
itemView.findViewById<View>(R.id.country_list_item).setOnClickListener {
|
||||||
|
Preference.putCountryNameResID(TracerApp.AppContext, countryNameResId)
|
||||||
|
Preference.putCallingCode(TracerApp.AppContext, callingCode)
|
||||||
|
Preference.putNationalFlagResID(TracerApp.AppContext, flagResID)
|
||||||
|
|
||||||
|
onCountryClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CountryListRecyclerViewAdapter(
|
||||||
|
private val context: Context,
|
||||||
|
private val countryListItem: List<CountryListItemInterface>,
|
||||||
|
private val onCountryClicked: () -> Unit
|
||||||
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): RecyclerView.ViewHolder {
|
||||||
|
return when (viewType) {
|
||||||
|
VIEW_TYPE_GROUP_TITLE -> CountryGroupTitleHolder(
|
||||||
|
LayoutInflater.from(context).inflate(
|
||||||
|
R.layout.view_list_item_group_title,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else -> CountryListItemHolder(
|
||||||
|
LayoutInflater.from(context).inflate(
|
||||||
|
R.layout.view_list_item_country,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
onCountryClicked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
return when (countryListItem[position]) {
|
||||||
|
is CountryGroupTitle -> VIEW_TYPE_GROUP_TITLE
|
||||||
|
else -> VIEW_TYPE_COUNTRY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return countryListItem.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
when (holder) {
|
||||||
|
is CountryGroupTitleHolder -> {
|
||||||
|
val title = context.getString((countryListItem[position] as CountryGroupTitle).titleResId)
|
||||||
|
holder.setCountryGroupTitle(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
is CountryListItemHolder -> {
|
||||||
|
val countryListItem = (countryListItem[position] as CountryListItem)
|
||||||
|
val countryName = context.getString(countryListItem.countryNameResId)
|
||||||
|
|
||||||
|
holder.setCountryListItem(
|
||||||
|
countryListItem.countryNameResId,
|
||||||
|
countryName,
|
||||||
|
countryListItem.callingCode,
|
||||||
|
countryListItem.flagResID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,35 @@
|
||||||
package au.gov.health.covidsafe.ui.onboarding.fragment.enternumber
|
package au.gov.health.covidsafe.ui.onboarding.fragment.enternumber
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.view.KeyEvent
|
||||||
import android.text.InputFilter
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.text.method.LinkMovementMethod
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.TextView.OnEditorActionListener
|
||||||
import androidx.annotation.NavigationRes
|
import androidx.annotation.NavigationRes
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import au.gov.health.covidsafe.Preference
|
||||||
import au.gov.health.covidsafe.R
|
import au.gov.health.covidsafe.R
|
||||||
import au.gov.health.covidsafe.TracerApp
|
import au.gov.health.covidsafe.TracerApp
|
||||||
import au.gov.health.covidsafe.ui.PagerChildFragment
|
import au.gov.health.covidsafe.ui.PagerChildFragment
|
||||||
import au.gov.health.covidsafe.ui.UploadButtonLayout
|
import au.gov.health.covidsafe.ui.UploadButtonLayout
|
||||||
|
import au.gov.health.covidsafe.ui.onboarding.CountryCodeSelectionActivity
|
||||||
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_CALLING_CODE
|
||||||
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_CHALLENGE_NAME
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_CHALLENGE_NAME
|
||||||
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_DESTINATION_ID
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_DESTINATION_ID
|
||||||
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_PHONE_NUMBER
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_PHONE_NUMBER
|
||||||
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_PROGRESS
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_PROGRESS
|
||||||
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_SESSION
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enterpin.EnterPinFragment.Companion.ENTER_PIN_SESSION
|
||||||
import kotlinx.android.synthetic.main.fragment_enter_number.*
|
import kotlinx.android.synthetic.main.fragment_enter_number.*
|
||||||
import kotlinx.android.synthetic.main.fragment_enter_number.view.*
|
|
||||||
|
|
||||||
class EnterNumberFragment : PagerChildFragment() {
|
class EnterNumberFragment : PagerChildFragment() {
|
||||||
|
|
||||||
|
@ -36,30 +43,21 @@ class EnterNumberFragment : PagerChildFragment() {
|
||||||
|
|
||||||
private val enterNumberPresenter = EnterNumberPresenter(this)
|
private val enterNumberPresenter = EnterNumberPresenter(this)
|
||||||
private var alertDialog: AlertDialog? = null
|
private var alertDialog: AlertDialog? = null
|
||||||
|
|
||||||
@NavigationRes
|
@NavigationRes
|
||||||
private var destinationId: Int? = null
|
private var destinationId: Int? = null
|
||||||
|
|
||||||
private val phoneNumberTextWatcher: TextWatcher = object : TextWatcher {
|
private lateinit var countryName: String
|
||||||
override fun afterTextChanged(s: Editable?) {
|
private var callingCode: Int = 0
|
||||||
// change LengthFilter if user making a mistake of entering phone number starting with 0
|
private var nationalFlagResID: Int = 0
|
||||||
val phoneNumberLength = TracerApp.AppContext.resources.getInteger(R.integer.australian_phone_number_length)
|
|
||||||
val filters = enter_number_phone_number.filters
|
|
||||||
val newFilterLength = if (s?.toString()?.startsWith("0") == true) {
|
|
||||||
phoneNumberLength + 1
|
|
||||||
} else {
|
|
||||||
phoneNumberLength
|
|
||||||
}
|
|
||||||
enter_number_phone_number.filters = filters.filterNot { it is InputFilter.LengthFilter }.toTypedArray() +
|
|
||||||
InputFilter.LengthFilter(newFilterLength)
|
|
||||||
|
|
||||||
updateButtonState()
|
private val errorTextColor = ContextCompat.getColor(TracerApp.AppContext, R.color.error)
|
||||||
}
|
private val normalTextColor = ContextCompat.getColor(TracerApp.AppContext, R.color.slack_black)
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
private fun updateSelectedCountry() {
|
||||||
}
|
countryName = getString(Preference.getCountryNameResID(this.requireContext()))
|
||||||
|
callingCode = Preference.getCallingCode(this.requireContext())
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
nationalFlagResID = Preference.getNationalFlagResID(this.requireContext())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)
|
||||||
|
@ -67,7 +65,7 @@ class EnterNumberFragment : PagerChildFragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
view.use_oz_phone_number.movementMethod = LinkMovementMethod.getInstance()
|
|
||||||
arguments?.let {
|
arguments?.let {
|
||||||
destinationId = it.getInt(ENTER_NUMBER_DESTINATION_ID)
|
destinationId = it.getInt(ENTER_NUMBER_DESTINATION_ID)
|
||||||
stepProgress = if (it.containsKey(ENTER_NUMBER_PROGRESS)) it.getInt(ENTER_PIN_PROGRESS) else null
|
stepProgress = if (it.containsKey(ENTER_NUMBER_PROGRESS)) it.getInt(ENTER_PIN_PROGRESS) else null
|
||||||
|
@ -76,26 +74,74 @@ class EnterNumberFragment : PagerChildFragment() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
enter_number_phone_number.selectAll()
|
|
||||||
enter_number_phone_number.addTextChangedListener(phoneNumberTextWatcher)
|
updateSelectedCountry()
|
||||||
|
|
||||||
|
enter_number_phone_number.addTextChangedListener {
|
||||||
|
enter_number_phone_number.setTextColor(normalTextColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
enter_number_phone_number.setOnEditorActionListener { _, actionId, event ->
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
|
||||||
|
actionId == EditorInfo.IME_ACTION_DONE ||
|
||||||
|
event != null &&
|
||||||
|
event.action == KeyEvent.ACTION_DOWN &&
|
||||||
|
event.keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||||
|
|
||||||
|
if (event == null || !event.isShiftPressed) {
|
||||||
|
// user has done typing.
|
||||||
updateButtonState()
|
updateButtonState()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
enter_number_phone_number.removeTextChangedListener(phoneNumberTextWatcher)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showInvalidPhoneNumber() {
|
false // pass on to other listeners.
|
||||||
invalid_phone_number.visibility = VISIBLE
|
}
|
||||||
|
|
||||||
|
updateButtonState()
|
||||||
|
displaySelectedCountryOrRegion()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private fun displaySelectedCountryOrRegion() {
|
||||||
|
country_name_code.text = "$countryName(+$callingCode)"
|
||||||
|
national_flag.setImageResource(nationalFlagResID)
|
||||||
|
|
||||||
|
country_selection_box.setOnClickListener {
|
||||||
|
startActivity(Intent(this.requireContext(), CountryCodeSelectionActivity::class.java))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideInvalidPhoneNumberPrompt() {
|
||||||
|
enter_number_headline.setTextColor(normalTextColor)
|
||||||
|
enter_number_phone_number.background = context?.getDrawable(R.drawable.edittext_modified_states)
|
||||||
|
enter_number_phone_number.setTextColor(normalTextColor)
|
||||||
|
invalid_phone_number.visibility = GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showInvalidPhoneNumberPrompt(errorMessageResID: Int) {
|
||||||
|
enter_number_headline.setTextColor(errorTextColor)
|
||||||
enter_number_phone_number.background = context?.getDrawable(R.drawable.phone_number_invalid_background)
|
enter_number_phone_number.background = context?.getDrawable(R.drawable.phone_number_invalid_background)
|
||||||
|
enter_number_phone_number.setTextColor(errorTextColor)
|
||||||
|
invalid_phone_number.visibility = VISIBLE
|
||||||
|
invalid_phone_number.setText(errorMessageResID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateButtonState() {
|
override fun updateButtonState() {
|
||||||
if (enterNumberPresenter.validateAuNumber(enter_number_phone_number?.text?.toString())) {
|
val phoneNumberValidity = enterNumberPresenter.validatePhoneNumber(
|
||||||
|
callingCode,
|
||||||
|
enter_number_phone_number.text.toString().trim()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (phoneNumberValidity.first) {
|
||||||
enableContinueButton()
|
enableContinueButton()
|
||||||
|
|
||||||
|
hideInvalidPhoneNumberPrompt()
|
||||||
} else {
|
} else {
|
||||||
disableContinueButton()
|
disableContinueButton()
|
||||||
|
|
||||||
|
if (enter_number_phone_number.text.toString().isNotEmpty()) {
|
||||||
|
showInvalidPhoneNumberPrompt(phoneNumberValidity.second)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +156,12 @@ class EnterNumberFragment : PagerChildFragment() {
|
||||||
fun navigateToOTPPage(
|
fun navigateToOTPPage(
|
||||||
session: String?,
|
session: String?,
|
||||||
challengeName: String?,
|
challengeName: String?,
|
||||||
|
callingCode: Int,
|
||||||
phoneNumber: String) {
|
phoneNumber: String) {
|
||||||
val bundle = bundleOf(
|
val bundle = bundleOf(
|
||||||
ENTER_PIN_SESSION to session,
|
ENTER_PIN_SESSION to session,
|
||||||
ENTER_PIN_CHALLENGE_NAME to challengeName,
|
ENTER_PIN_CHALLENGE_NAME to challengeName,
|
||||||
|
ENTER_PIN_CALLING_CODE to callingCode,
|
||||||
ENTER_PIN_PHONE_NUMBER to phoneNumber,
|
ENTER_PIN_PHONE_NUMBER to phoneNumber,
|
||||||
ENTER_PIN_DESTINATION_ID to destinationId).also { bundle ->
|
ENTER_PIN_DESTINATION_ID to destinationId).also { bundle ->
|
||||||
stepProgress?.let {
|
stepProgress?.let {
|
||||||
|
@ -130,7 +178,7 @@ class EnterNumberFragment : PagerChildFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUploadButtonLayout() = UploadButtonLayout.ContinueLayout(R.string.enter_number_button) {
|
override fun getUploadButtonLayout() = UploadButtonLayout.ContinueLayout(R.string.enter_number_button) {
|
||||||
enterNumberPresenter.requestOTP(enter_number_phone_number.text.toString().trim())
|
enterNumberPresenter.requestOTP(callingCode, enter_number_phone_number.text.toString().trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showCheckInternetError() {
|
fun showCheckInternetError() {
|
||||||
|
|
|
@ -6,19 +6,21 @@ import androidx.lifecycle.LifecycleObserver
|
||||||
import androidx.lifecycle.OnLifecycleEvent
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
import au.gov.health.covidsafe.Preference
|
import au.gov.health.covidsafe.Preference
|
||||||
import au.gov.health.covidsafe.R
|
import au.gov.health.covidsafe.R
|
||||||
import au.gov.health.covidsafe.TracerApp
|
|
||||||
import au.gov.health.covidsafe.extensions.isInternetAvailable
|
import au.gov.health.covidsafe.extensions.isInternetAvailable
|
||||||
import au.gov.health.covidsafe.factory.NetworkFactory
|
import au.gov.health.covidsafe.factory.NetworkFactory
|
||||||
import au.gov.health.covidsafe.interactor.usecase.GetOnboardingOtp
|
import au.gov.health.covidsafe.interactor.usecase.GetOnboardingOtp
|
||||||
import au.gov.health.covidsafe.interactor.usecase.GetOnboardingOtpException
|
import au.gov.health.covidsafe.interactor.usecase.GetOnboardingOtpException
|
||||||
import au.gov.health.covidsafe.interactor.usecase.GetOtpParams
|
import au.gov.health.covidsafe.interactor.usecase.GetOtpParams
|
||||||
|
|
||||||
|
const val AUSTRALIA_CALLING_CODE = 61
|
||||||
|
const val AUSTRALIA_MOBILE_NUMBER_LENGTH = 9
|
||||||
|
const val AUSTRALIA_MOBILE_NUMBER_PREFIX_DIGIT = "0"
|
||||||
|
const val NORFOLK_ISLAND_CALLING_CODE = 672
|
||||||
|
const val NORFOLK_ISLAND_MOBILE_NUMBER_LENGTH = 5
|
||||||
|
const val NORFOLK_ISLAND_MOBILE_PREFIX_DIGIT = "3"
|
||||||
|
|
||||||
class EnterNumberPresenter(private val enterNumberFragment: EnterNumberFragment) : LifecycleObserver {
|
class EnterNumberPresenter(private val enterNumberFragment: EnterNumberFragment) : LifecycleObserver {
|
||||||
|
|
||||||
private val TAG = this.javaClass.simpleName
|
|
||||||
|
|
||||||
private lateinit var phoneNumber: String
|
|
||||||
private lateinit var getOnboardingOtp: GetOnboardingOtp
|
private lateinit var getOnboardingOtp: GetOnboardingOtp
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -30,47 +32,49 @@ class EnterNumberPresenter(private val enterNumberFragment: EnterNumberFragment)
|
||||||
getOnboardingOtp = GetOnboardingOtp(NetworkFactory.awsClient, enterNumberFragment.lifecycle)
|
getOnboardingOtp = GetOnboardingOtp(NetworkFactory.awsClient, enterNumberFragment.lifecycle)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun requestOTP(phoneNumber: String) {
|
fun requestOTP(callingCode: Int, phoneNumber: String) {
|
||||||
|
val prefixZeroRemovedPhoneNumber =
|
||||||
|
adjustPrefixForAustralianAndNorfolkPhoneNumber(callingCode, phoneNumber)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
enterNumberFragment.activity?.isInternetAvailable() == false -> {
|
enterNumberFragment.activity?.isInternetAvailable() == false -> {
|
||||||
enterNumberFragment.showCheckInternetError()
|
enterNumberFragment.showCheckInternetError()
|
||||||
}
|
}
|
||||||
validateAuNumber(phoneNumber) -> {
|
else -> makeOTPCall(callingCode, prefixZeroRemovedPhoneNumber)
|
||||||
val cleansedNumber = if (phoneNumber.startsWith("0")) {
|
|
||||||
phoneNumber.takeLast(TracerApp.AppContext.resources.getInteger(R.integer.australian_phone_number_length))
|
|
||||||
} else phoneNumber
|
|
||||||
val fullNumber = "${enterNumberFragment.resources.getString(R.string.enter_number_prefix)}$cleansedNumber"
|
|
||||||
Preference.putPhoneNumber(TracerApp.AppContext, fullNumber)
|
|
||||||
this.phoneNumber = cleansedNumber
|
|
||||||
makeOTPCall(cleansedNumber)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
enterNumberFragment.showInvalidPhoneNumber()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param phoneNumber cleansed phone number, 9 digits, doesn't start with 0
|
* if [callingCode] is 61 for Australia, then [phoneNumber] should be a prefix removed
|
||||||
|
* Australian phone number: 9 digits, doesn't start with 0.
|
||||||
|
* Otherwise [phoneNumber] can be any number and the validation should be done in the backend
|
||||||
*/
|
*/
|
||||||
private fun makeOTPCall(phoneNumber: String) {
|
private fun makeOTPCall(callingCode: Int, phoneNumber: String) {
|
||||||
enterNumberFragment.activity?.let {
|
enterNumberFragment.activity?.let {
|
||||||
enterNumberFragment.disableContinueButton()
|
enterNumberFragment.disableContinueButton()
|
||||||
enterNumberFragment.showLoading()
|
enterNumberFragment.showLoading()
|
||||||
getOnboardingOtp.invoke(GetOtpParams(phoneNumber,
|
|
||||||
Preference.getDeviceID(enterNumberFragment.requireContext()),
|
val context = enterNumberFragment.requireContext()
|
||||||
Preference.getPostCode(enterNumberFragment.requireContext()),
|
|
||||||
Preference.getAge(enterNumberFragment.requireContext()),
|
getOnboardingOtp.invoke(
|
||||||
Preference.getName(enterNumberFragment.requireContext())),
|
GetOtpParams(
|
||||||
|
countryCode = "+$callingCode",
|
||||||
|
phoneNumber = phoneNumber,
|
||||||
|
deviceId = Preference.getDeviceID(context),
|
||||||
|
postCode = Preference.getPostCode(context),
|
||||||
|
age = Preference.getAge(context),
|
||||||
|
name = Preference.getName(context)
|
||||||
|
),
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
enterNumberFragment.navigateToOTPPage(
|
enterNumberFragment.navigateToOTPPage(
|
||||||
it.session,
|
it.session,
|
||||||
it.challengeName,
|
it.challengeName,
|
||||||
|
callingCode,
|
||||||
phoneNumber)
|
phoneNumber)
|
||||||
},
|
},
|
||||||
onFailure = {
|
onFailure = {
|
||||||
if (it is GetOnboardingOtpException.GetOtpInvalidNumberException) {
|
if (it is GetOnboardingOtpException.GetOtpInvalidNumberException) {
|
||||||
enterNumberFragment.showInvalidPhoneNumber()
|
enterNumberFragment.showInvalidPhoneNumberPrompt(R.string.invalid_phone_number)
|
||||||
} else {
|
} else {
|
||||||
enterNumberFragment.showGenericError()
|
enterNumberFragment.showGenericError()
|
||||||
}
|
}
|
||||||
|
@ -80,12 +84,46 @@ class EnterNumberPresenter(private val enterNumberFragment: EnterNumberFragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun validateAuNumber(phoneNumber: String?): Boolean {
|
fun validatePhoneNumber(callingCode: Int, phoneNumber: String): Pair<Boolean, Int> {
|
||||||
var australianPhoneNumberLength = enterNumberFragment.resources.getInteger(R.integer.australian_phone_number_length)
|
val isNumberValid = when (callingCode) {
|
||||||
if (phoneNumber?.startsWith("0") == true) {
|
AUSTRALIA_CALLING_CODE -> {
|
||||||
australianPhoneNumberLength++
|
if (phoneNumber.startsWith(AUSTRALIA_MOBILE_NUMBER_PREFIX_DIGIT)) {
|
||||||
|
phoneNumber.length == AUSTRALIA_MOBILE_NUMBER_LENGTH + 1
|
||||||
|
} else {
|
||||||
|
phoneNumber.length == AUSTRALIA_MOBILE_NUMBER_LENGTH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NORFOLK_ISLAND_CALLING_CODE -> {
|
||||||
|
if (phoneNumber.startsWith(NORFOLK_ISLAND_MOBILE_PREFIX_DIGIT)) {
|
||||||
|
phoneNumber.length == NORFOLK_ISLAND_MOBILE_NUMBER_LENGTH + 1
|
||||||
|
} else {
|
||||||
|
phoneNumber.length == NORFOLK_ISLAND_MOBILE_NUMBER_LENGTH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
val errorMessageResID = when (callingCode) {
|
||||||
|
AUSTRALIA_CALLING_CODE -> R.string.invalid_australian_phone_number_error_prompt
|
||||||
|
NORFOLK_ISLAND_CALLING_CODE -> R.string.invalid_norfolk_island_phone_number_error_prompt
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pair(isNumberValid, errorMessageResID)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun adjustPrefixForAustralianAndNorfolkPhoneNumber(callingCode: Int, phoneNumber: String): String {
|
||||||
|
return when (callingCode) {
|
||||||
|
AUSTRALIA_CALLING_CODE -> phoneNumber.removePrefix(AUSTRALIA_MOBILE_NUMBER_PREFIX_DIGIT)
|
||||||
|
NORFOLK_ISLAND_CALLING_CODE -> {
|
||||||
|
if (phoneNumber.length == NORFOLK_ISLAND_MOBILE_NUMBER_LENGTH) {
|
||||||
|
"$NORFOLK_ISLAND_MOBILE_PREFIX_DIGIT$phoneNumber"
|
||||||
|
} else {
|
||||||
|
phoneNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> phoneNumber
|
||||||
}
|
}
|
||||||
return (phoneNumber?.length ?: 0) == australianPhoneNumberLength
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@ class EnterPinFragment : PagerChildFragment() {
|
||||||
companion object {
|
companion object {
|
||||||
const val ENTER_PIN_SESSION = "session"
|
const val ENTER_PIN_SESSION = "session"
|
||||||
const val ENTER_PIN_CHALLENGE_NAME = "challenge_name"
|
const val ENTER_PIN_CHALLENGE_NAME = "challenge_name"
|
||||||
|
const val ENTER_PIN_CALLING_CODE = "calling_code"
|
||||||
const val ENTER_PIN_PHONE_NUMBER = "phone_number"
|
const val ENTER_PIN_PHONE_NUMBER = "phone_number"
|
||||||
const val ENTER_PIN_DESTINATION_ID = "destination_id"
|
const val ENTER_PIN_DESTINATION_ID = "destination_id"
|
||||||
const val ENTER_PIN_PROGRESS = "progress"
|
const val ENTER_PIN_PROGRESS = "progress"
|
||||||
|
@ -48,13 +49,18 @@ class EnterPinFragment : PagerChildFragment() {
|
||||||
arguments?.let {
|
arguments?.let {
|
||||||
val session = it.getString(ENTER_PIN_SESSION)
|
val session = it.getString(ENTER_PIN_SESSION)
|
||||||
val challengeName = it.getString(ENTER_PIN_CHALLENGE_NAME)
|
val challengeName = it.getString(ENTER_PIN_CHALLENGE_NAME)
|
||||||
|
val callingCode = it.getInt(ENTER_PIN_CALLING_CODE)
|
||||||
val phoneNumber = it.getString(ENTER_PIN_PHONE_NUMBER)
|
val phoneNumber = it.getString(ENTER_PIN_PHONE_NUMBER)
|
||||||
destinationId = it.getInt(ENTER_PIN_DESTINATION_ID)
|
destinationId = it.getInt(ENTER_PIN_DESTINATION_ID)
|
||||||
|
|
||||||
stepProgress = if (it.containsKey(ENTER_PIN_PROGRESS)) it.getInt(ENTER_PIN_PROGRESS) else null
|
stepProgress = if (it.containsKey(ENTER_PIN_PROGRESS)) it.getInt(ENTER_PIN_PROGRESS) else null
|
||||||
enter_pin_headline.text = resources.getString(R.string.enter_pin_headline, resources.getString(R.string.enter_number_prefix), phoneNumber)
|
|
||||||
|
enter_pin_headline.text = resources.getString(R.string.enter_pin_headline, "+$callingCode", phoneNumber)
|
||||||
|
|
||||||
presenter = EnterPinPresenter(this@EnterPinFragment,
|
presenter = EnterPinPresenter(this@EnterPinFragment,
|
||||||
session,
|
session,
|
||||||
challengeName,
|
challengeName,
|
||||||
|
callingCode,
|
||||||
phoneNumber)
|
phoneNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import retrofit2.Response
|
||||||
class EnterPinPresenter(private val enterPinFragment: EnterPinFragment,
|
class EnterPinPresenter(private val enterPinFragment: EnterPinFragment,
|
||||||
private var session: String?,
|
private var session: String?,
|
||||||
private var challengeName: String?,
|
private var challengeName: String?,
|
||||||
|
private val callingCode: Int,
|
||||||
private val phoneNumber: String?) : LifecycleObserver {
|
private val phoneNumber: String?) : LifecycleObserver {
|
||||||
|
|
||||||
private val TAG = this.javaClass.simpleName
|
private val TAG = this.javaClass.simpleName
|
||||||
|
@ -45,11 +46,17 @@ class EnterPinPresenter(private val enterPinFragment: EnterPinFragment,
|
||||||
enterPinFragment.showGenericError()
|
enterPinFragment.showGenericError()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
getOtp.invoke(GetOtpParams(phoneNumber,
|
val context = enterPinFragment.requireContext()
|
||||||
Preference.getDeviceID(enterPinFragment.requireContext()),
|
|
||||||
Preference.getPostCode(enterPinFragment.requireContext()),
|
getOtp.invoke(
|
||||||
Preference.getAge(enterPinFragment.requireContext()),
|
GetOtpParams(
|
||||||
Preference.getName(enterPinFragment.requireContext())),
|
countryCode = "+$callingCode",
|
||||||
|
phoneNumber = phoneNumber,
|
||||||
|
deviceId = Preference.getDeviceID(context),
|
||||||
|
postCode = Preference.getPostCode(context),
|
||||||
|
age = Preference.getAge(context),
|
||||||
|
name = Preference.getName(context)
|
||||||
|
),
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
session = it.session
|
session = it.session
|
||||||
challengeName = it.challengeName
|
challengeName = it.challengeName
|
||||||
|
|
|
@ -3,20 +3,27 @@ package au.gov.health.covidsafe.ui.onboarding.fragment.personal
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.view.KeyEvent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.accessibility.AccessibilityEvent
|
import android.view.accessibility.AccessibilityEvent
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.NumberPicker
|
import android.widget.NumberPicker
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import au.gov.health.covidsafe.Preference
|
||||||
import au.gov.health.covidsafe.R
|
import au.gov.health.covidsafe.R
|
||||||
import au.gov.health.covidsafe.ui.PagerChildFragment
|
import au.gov.health.covidsafe.ui.PagerChildFragment
|
||||||
import au.gov.health.covidsafe.ui.UploadButtonLayout
|
import au.gov.health.covidsafe.ui.UploadButtonLayout
|
||||||
import au.gov.health.covidsafe.ui.onboarding.fragment.enternumber.EnterNumberFragment
|
import au.gov.health.covidsafe.ui.onboarding.fragment.enternumber.EnterNumberFragment
|
||||||
|
import kotlinx.android.synthetic.main.fragment_enter_number.*
|
||||||
import kotlinx.android.synthetic.main.fragment_personal_details.*
|
import kotlinx.android.synthetic.main.fragment_personal_details.*
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
||||||
|
private val POST_CODE_REGEX = Pattern.compile("^(?:(?:[2-8]\\d|9[0-7]|0?[28]|0?9(?=09))(?:\\d{2}))$")
|
||||||
|
|
||||||
class PersonalDetailsFragment : PagerChildFragment() {
|
class PersonalDetailsFragment : PagerChildFragment() {
|
||||||
|
|
||||||
|
@ -25,122 +32,39 @@ class PersonalDetailsFragment : PagerChildFragment() {
|
||||||
private var alertDialog: AlertDialog? = null
|
private var alertDialog: AlertDialog? = null
|
||||||
override var stepProgress: Int? = 1
|
override var stepProgress: Int? = 1
|
||||||
override val navigationIcon: Int = R.drawable.ic_up
|
override val navigationIcon: Int = R.drawable.ic_up
|
||||||
private var ageSelected: Pair<String, String>? = null
|
|
||||||
|
|
||||||
private val presenter = PersonalDetailsPresenter(this)
|
private var ageSelected: Pair<Int, String> = Pair(-1, "")
|
||||||
|
|
||||||
private val nameTextWatcher: TextWatcher = object : TextWatcher {
|
private lateinit var name: String
|
||||||
override fun afterTextChanged(s: Editable?) {
|
private lateinit var postcode: String
|
||||||
hideNameError()
|
private var age: Int = -1
|
||||||
updateButtonState()
|
|
||||||
|
private fun updatePersonalDetailsDataField() {
|
||||||
|
name = personal_details_name.text.toString()
|
||||||
|
postcode = personal_details_post_code.text.toString()
|
||||||
|
age = ageSelected.first
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
private fun isFullName() = name.trim().length > 1
|
||||||
}
|
private fun isValidAge() = age >= 0
|
||||||
|
private fun isValidPostcode() = postcode.length == 4 && POST_CODE_REGEX.matcher(postcode).matches()
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val postCodeTextWatcher: TextWatcher = object : TextWatcher {
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
presenter.validateInlinePostCode(s.toString())
|
|
||||||
updateButtonState()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)
|
||||||
: View? = inflater.inflate(R.layout.fragment_personal_details, container, false)
|
: View? = inflater.inflate(R.layout.fragment_personal_details, container, false)
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
personal_details_name.addTextChangedListener(nameTextWatcher)
|
|
||||||
personal_details_post_code.addTextChangedListener(postCodeTextWatcher)
|
|
||||||
personal_details_age.setOnClickListener {
|
|
||||||
showAgePicker()
|
|
||||||
}
|
|
||||||
personal_details_age.text = ageSelected?.second
|
|
||||||
|
|
||||||
// set accessibility focus to the title "Enter your details"
|
personal_details_age.setText(ageSelected.second)
|
||||||
personal_details_headline.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
fun showAgePicker() {
|
||||||
super.onPause()
|
|
||||||
personal_details_name.removeTextChangedListener(nameTextWatcher)
|
|
||||||
personal_details_post_code.removeTextChangedListener(postCodeTextWatcher)
|
|
||||||
personal_details_age.setOnClickListener(null)
|
|
||||||
alertDialog?.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getUploadButtonLayout(): UploadButtonLayout = UploadButtonLayout.ContinueLayout(R.string.personal_details_button) {
|
|
||||||
presenter.saveInfos(personal_details_name.text.toString(), personal_details_post_code.text.toString(), getMidAgeToSend())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateButtonState() {
|
|
||||||
if (presenter.validateInputsForButtonUpdate(personal_details_name.text.toString(), personal_details_post_code.text.toString(), getMidAgeToSend())) {
|
|
||||||
enableContinueButton()
|
|
||||||
} else {
|
|
||||||
disableContinueButton()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showGenericError() {
|
|
||||||
activity?.let { activity ->
|
|
||||||
alertDialog?.dismiss()
|
|
||||||
alertDialog = AlertDialog.Builder(activity)
|
|
||||||
.setMessage(R.string.generic_error)
|
|
||||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
|
||||||
.setPositiveButton(android.R.string.yes, null).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun navigateToNextPage(minor: Boolean) {
|
|
||||||
if (minor) {
|
|
||||||
navigateTo(PersonalDetailsFragmentDirections.actionPersonalDetailsToUnderSixteenFragment().actionId)
|
|
||||||
} else {
|
|
||||||
val bundle = bundleOf(
|
|
||||||
EnterNumberFragment.ENTER_NUMBER_DESTINATION_ID to R.id.action_otpFragment_to_permissionFragment,
|
|
||||||
EnterNumberFragment.ENTER_NUMBER_PROGRESS to 2)
|
|
||||||
navigateTo(PersonalDetailsFragmentDirections.actionPersonalDetailsToEnterNumberFragment().actionId, bundle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showPostcodeError() {
|
|
||||||
personal_details_post_code_error.visibility = VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hidePostcodeError() {
|
|
||||||
personal_details_post_code_error.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showNameError() {
|
|
||||||
personal_details_name_error.visibility = VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hideNameError() {
|
|
||||||
personal_details_name_error.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showAgeError() {
|
|
||||||
personal_details_age_error.visibility = VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hideAgeError() {
|
|
||||||
personal_details_age_error.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showAgePicker() {
|
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
val ages = resources.getStringArray(R.array.personal_details_age_array).map {
|
val ages = resources.getStringArray(R.array.personal_details_age_array).map {
|
||||||
it.split(":").let { it[0] to it[1] }
|
it.split(":").let { split ->
|
||||||
|
(split[0]).toInt() to split[1]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var selected = ages.firstOrNull { it == ageSelected }?.let {
|
var selected = ages.firstOrNull { it == ageSelected }?.let {
|
||||||
ages.indexOf(it)
|
ages.indexOf(it)
|
||||||
} ?: 0
|
} ?: 0
|
||||||
|
@ -159,24 +83,127 @@ class PersonalDetailsFragment : PagerChildFragment() {
|
||||||
.setView(picker)
|
.setView(picker)
|
||||||
.setPositiveButton(R.string.personal_details_dialog_ok) { _, _ ->
|
.setPositiveButton(R.string.personal_details_dialog_ok) { _, _ ->
|
||||||
ageSelected = ages[selected]
|
ageSelected = ages[selected]
|
||||||
personal_details_age.text = ages[selected].second
|
|
||||||
hideAgeError()
|
personal_details_age.setText(ageSelected.second)
|
||||||
|
|
||||||
|
updatePersonalDetailsDataField()
|
||||||
updateButtonState()
|
updateButtonState()
|
||||||
|
|
||||||
|
personal_details_age_error.visibility =
|
||||||
|
if (isValidAge()) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
personal_details_post_code.requestFocus()
|
||||||
}
|
}
|
||||||
.setNegativeButton(android.R.string.no, null)
|
.setNegativeButton(android.R.string.no, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMidAgeToSend(): String? {
|
personal_details_name.setOnFocusChangeListener { _, hasFocus ->
|
||||||
val ages = resources.getStringArray(R.array.personal_details_age_array).map {
|
updatePersonalDetailsDataField()
|
||||||
it.split(":").let { it[0] to it[1] }
|
updateButtonState()
|
||||||
|
|
||||||
|
personal_details_name_error.visibility = if (hasFocus || isFullName()) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
}
|
}
|
||||||
val selected = ages.firstOrNull { it == ageSelected }?.let {
|
|
||||||
ages.indexOf(it)
|
|
||||||
}
|
}
|
||||||
return selected?.let {
|
|
||||||
ages[selected].first
|
personal_details_post_code.setOnFocusChangeListener { _, hasFocus ->
|
||||||
|
if(hasFocus) {
|
||||||
|
updatePersonalDetailsDataField()
|
||||||
|
updateButtonState()
|
||||||
|
|
||||||
|
personal_details_age_error.visibility =
|
||||||
|
if (isValidAge()) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
personal_details_post_code.setOnEditorActionListener { _, actionId, event ->
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
|
||||||
|
actionId == EditorInfo.IME_ACTION_DONE ||
|
||||||
|
event != null &&
|
||||||
|
event.action == KeyEvent.ACTION_DOWN &&
|
||||||
|
event.keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||||
|
|
||||||
|
if (event == null || !event.isShiftPressed) {
|
||||||
|
// user has done typing.
|
||||||
|
updatePersonalDetailsDataField()
|
||||||
|
updateButtonState()
|
||||||
|
|
||||||
|
personal_details_age_error.visibility =
|
||||||
|
if (isValidAge()) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
personal_details_post_code_error.visibility = if (isValidPostcode()) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false // pass on to other listeners.
|
||||||
|
}
|
||||||
|
|
||||||
|
personal_details_age.setOnFocusChangeListener { _, hasFocus ->
|
||||||
|
if(hasFocus){
|
||||||
|
showAgePicker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
personal_details_age.setOnClickListener {
|
||||||
|
showAgePicker()
|
||||||
|
}
|
||||||
|
|
||||||
|
// set accessibility focus to the title "Enter your details"
|
||||||
|
personal_details_headline.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
alertDialog?.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getUploadButtonLayout(): UploadButtonLayout = UploadButtonLayout.ContinueLayout(R.string.personal_details_button) {
|
||||||
|
val context = this.requireContext()
|
||||||
|
Preference.putName(context, name)
|
||||||
|
Preference.putAge(context, "$age")
|
||||||
|
Preference.putPostCode(context, postcode)
|
||||||
|
|
||||||
|
navigateToNextPage(age < 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateButtonState() {
|
||||||
|
updatePersonalDetailsDataField()
|
||||||
|
|
||||||
|
if (isFullName() && isValidAge() && isValidPostcode()) {
|
||||||
|
enableContinueButton()
|
||||||
|
} else {
|
||||||
|
disableContinueButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun navigateToNextPage(isUnder16: Boolean) {
|
||||||
|
if (isUnder16) {
|
||||||
|
navigateTo(PersonalDetailsFragmentDirections.actionPersonalDetailsToUnderSixteenFragment().actionId)
|
||||||
|
} else {
|
||||||
|
val bundle = bundleOf(
|
||||||
|
EnterNumberFragment.ENTER_NUMBER_DESTINATION_ID to R.id.action_otpFragment_to_permissionFragment,
|
||||||
|
EnterNumberFragment.ENTER_NUMBER_PROGRESS to 2)
|
||||||
|
navigateTo(PersonalDetailsFragmentDirections.actionPersonalDetailsToEnterNumberFragment().actionId, bundle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,96 +0,0 @@
|
||||||
package au.gov.health.covidsafe.ui.onboarding.fragment.personal
|
|
||||||
|
|
||||||
import au.gov.health.covidsafe.Preference
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
class PersonalDetailsPresenter(private val personalDetailsFragment: PersonalDetailsFragment) {
|
|
||||||
|
|
||||||
private val TAG = this.javaClass.simpleName
|
|
||||||
|
|
||||||
private val POST_CODE_REGEX = Pattern.compile("^(?:(?:[2-8]\\d|9[0-7]|0?[28]|0?9(?=09))(?:\\d{2}))$")
|
|
||||||
|
|
||||||
fun saveInfos(name: String?, postCode: String?, age: String?) {
|
|
||||||
personalDetailsFragment.showLoading()
|
|
||||||
personalDetailsFragment.context?.let { context ->
|
|
||||||
val ageInt = age?.toIntOrNull()
|
|
||||||
val nameValid = name.isNullOrBlank().not()
|
|
||||||
val postCodeValid = postCode.isNullOrBlank().not() && isPostCodeValid(postCode)
|
|
||||||
val ageValid = age.isNullOrBlank().not()
|
|
||||||
|
|
||||||
if (nameValid && postCodeValid && ageValid) {
|
|
||||||
val valid = (name?.let { name ->
|
|
||||||
Preference.putName(context, name)
|
|
||||||
} ?: false) &&
|
|
||||||
(age?.let { age ->
|
|
||||||
Preference.putAge(context, age)
|
|
||||||
} ?: false) &&
|
|
||||||
(postCode?.let { postCode ->
|
|
||||||
Preference.putPostCode(context, postCode)
|
|
||||||
} ?: false)
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
personalDetailsFragment.hideLoading()
|
|
||||||
personalDetailsFragment.navigateToNextPage(ageInt?.let { it < 16 } ?: false)
|
|
||||||
} else {
|
|
||||||
personalDetailsFragment.hideLoading()
|
|
||||||
personalDetailsFragment.showGenericError()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showFieldsError(name, postCode, age)
|
|
||||||
personalDetailsFragment.hideLoading()
|
|
||||||
}
|
|
||||||
} ?: run {
|
|
||||||
personalDetailsFragment.hideLoading()
|
|
||||||
personalDetailsFragment.showGenericError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showFieldsError(name: String?, postCode: String?, age: String?) {
|
|
||||||
updateNameFieldError(name)
|
|
||||||
updateAgeFieldError(age)
|
|
||||||
updatePostcodeFieldError(postCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateAgeFieldError(age: String?) {
|
|
||||||
return if (age.isNullOrBlank()) {
|
|
||||||
personalDetailsFragment.showAgeError()
|
|
||||||
} else {
|
|
||||||
personalDetailsFragment.hideAgeError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNameFieldError(name: String?) {
|
|
||||||
return if (name.isNullOrBlank()) {
|
|
||||||
personalDetailsFragment.showNameError()
|
|
||||||
} else {
|
|
||||||
personalDetailsFragment.hideNameError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updatePostcodeFieldError(postCode: String?) {
|
|
||||||
return if (postCode.isNullOrBlank()) {
|
|
||||||
personalDetailsFragment.showPostcodeError()
|
|
||||||
} else {
|
|
||||||
personalDetailsFragment.hidePostcodeError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun validateInputsForButtonUpdate(name: String?, postCode: String?, age: String?): Boolean {
|
|
||||||
val nameValid = name.isNullOrBlank().not()
|
|
||||||
val postCodeValid = postCode.isNullOrBlank().not() && isPostCodeValid(postCode)
|
|
||||||
val ageValid = age.isNullOrBlank().not()
|
|
||||||
|
|
||||||
return nameValid && postCodeValid && ageValid
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun validateInlinePostCode(postCode: String?) {
|
|
||||||
if (!postCode.isNullOrEmpty() && postCode.length == 4 && !isPostCodeValid(postCode)) {
|
|
||||||
personalDetailsFragment.showPostcodeError()
|
|
||||||
} else {
|
|
||||||
personalDetailsFragment.hidePostcodeError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isPostCodeValid(postCode: String?) = POST_CODE_REGEX.matcher(postCode.toString()).matches()
|
|
||||||
|
|
||||||
}
|
|
9
app/src/main/res/drawable/ic_microphone.xml
Normal file
9
app/src/main/res/drawable/ic_microphone.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="14dp"
|
||||||
|
android:height="19dp"
|
||||||
|
android:viewportWidth="14"
|
||||||
|
android:viewportHeight="19">
|
||||||
|
<path
|
||||||
|
android:pathData="M12.2969,9.0156H13.9844C13.9844,10.7031 13.3906,12.1875 12.2031,13.4688C11.0469,14.7188 9.6406,15.4688 7.9844,15.7188V19H6.0156V15.7188C4.3594,15.4688 2.9375,14.7188 1.75,13.4688C0.5938,12.1875 0.0156,10.7031 0.0156,9.0156H1.7031C1.7031,10.4844 2.2188,11.7031 3.25,12.6719C4.3125,13.6094 5.5625,14.0781 7,14.0781C8.4375,14.0781 9.6719,13.6094 10.7031,12.6719C11.7656,11.7031 12.2969,10.4844 12.2969,9.0156ZM9.1094,11.125C8.5156,11.7188 7.8125,12.0156 7,12.0156C6.1875,12.0156 5.4844,11.7188 4.8906,11.125C4.2969,10.5312 4,9.8281 4,9.0156V3.0156C4,2.2031 4.2969,1.5 4.8906,0.9063C5.4844,0.3125 6.1875,0.0156 7,0.0156C7.8125,0.0156 8.5156,0.3125 9.1094,0.9063C9.7031,1.5 10,2.2031 10,3.0156V9.0156C10,9.8281 9.7031,10.5312 9.1094,11.125Z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
13
app/src/main/res/drawable/ic_right.xml
Normal file
13
app/src/main/res/drawable/ic_right.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="8dp"
|
||||||
|
android:height="14dp"
|
||||||
|
android:viewportWidth="8"
|
||||||
|
android:viewportHeight="14">
|
||||||
|
<path
|
||||||
|
android:pathData="M1,13L7,7L1,1"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#131313"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_search.xml
Normal file
9
app/src/main/res/drawable/ic_search.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="18dp"
|
||||||
|
android:height="18dp"
|
||||||
|
android:viewportWidth="18"
|
||||||
|
android:viewportHeight="18">
|
||||||
|
<path
|
||||||
|
android:pathData="M3.3281,9.7031C4.2031,10.5781 5.2656,11.0156 6.5156,11.0156C7.7656,11.0156 8.8281,10.5781 9.7031,9.7031C10.5781,8.8281 11.0156,7.7656 11.0156,6.5156C11.0156,5.2656 10.5781,4.2031 9.7031,3.3281C8.8281,2.4531 7.7656,2.0156 6.5156,2.0156C5.2656,2.0156 4.2031,2.4531 3.3281,3.3281C2.4531,4.2031 2.0156,5.2656 2.0156,6.5156C2.0156,7.7656 2.4531,8.8281 3.3281,9.7031ZM12.5156,11.0156L17.4844,15.9844L15.9844,17.4844L11.0156,12.5156V11.7188L10.7344,11.4375C9.5469,12.4688 8.1406,12.9844 6.5156,12.9844C4.7031,12.9844 3.1563,12.3594 1.875,11.1094C0.625,9.8594 0,8.3281 0,6.5156C0,4.7031 0.625,3.1719 1.875,1.9219C3.1563,0.6406 4.7031,0 6.5156,0C8.3281,0 9.8594,0.6406 11.1094,1.9219C12.3594,3.1719 12.9844,4.7031 12.9844,6.5156C12.9844,8.1406 12.4688,9.5469 11.4375,10.7344L11.7188,11.0156H12.5156Z"
|
||||||
|
android:fillColor="#666666"/>
|
||||||
|
</vector>
|
78
app/src/main/res/layout/activity_country_code_selection.xml
Normal file
78
app/src/main/res/layout/activity_country_code_selection.xml
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/countrySelectionToolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:navigationIcon="@drawable/ic_up"
|
||||||
|
app:navigationContentDescription="@string/navigation_back_button_content_description"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/keyline_6"
|
||||||
|
android:layout_marginStart="@dimen/keyline_1"
|
||||||
|
android:text="@string/search" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/keyline_8"
|
||||||
|
android:layout_marginStart="@dimen/keyline_1"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_1"
|
||||||
|
android:paddingTop="@dimen/keyline_0"
|
||||||
|
android:paddingBottom="@dimen/keyline_0"
|
||||||
|
android:paddingStart="@dimen/keyline_1"
|
||||||
|
android:paddingEnd="@dimen/keyline_0"
|
||||||
|
android:background="@drawable/edit_text_black_background">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/countrySearchImageView"
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:src="@drawable/ic_search"
|
||||||
|
android:focusable="false"
|
||||||
|
android:focusableInTouchMode="false"
|
||||||
|
android:clickable="false"
|
||||||
|
android:layout_gravity="center|start" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/countryRegionNameEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/transparent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/microphoneImageView"
|
||||||
|
android:layout_width="@dimen/keyline_6"
|
||||||
|
android:paddingStart="@dimen/keyline_1"
|
||||||
|
android:paddingEnd="@dimen/keyline_1"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:src="@drawable/ic_microphone" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginTop="@dimen/keyline_4"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/countryListRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/countryInitialLetterRecyclerView"
|
||||||
|
android:layout_width="@dimen/keyline_8"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="right" />
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
|
@ -12,41 +12,97 @@
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/enter_number_headline"
|
android:id="@+id/enter_number_page_headline"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/keyline_5"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:text="@string/enter_number_headline"
|
android:text="@string/enter_number_headline"
|
||||||
android:textAppearance="?textAppearanceHeadline2"
|
android:textAppearance="?textAppearanceHeadline2"
|
||||||
android:layout_marginStart="@dimen/keyline_5"
|
android:textSize="28sp"
|
||||||
android:layout_marginEnd="@dimen/keyline_5"
|
android:textStyle="bold"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/enter_number_prefix"
|
android:id="@+id/select_country_or_region"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/enter_number_prefix"
|
|
||||||
android:textColor="@color/slack_black"
|
|
||||||
android:textSize="@dimen/text_phone_number"
|
|
||||||
android:layout_marginStart="@dimen/keyline_5"
|
android:layout_marginStart="@dimen/keyline_5"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/enter_number_phone_number"
|
android:layout_marginTop="@dimen/keyline_5"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/select_country_or_region"
|
||||||
|
android:textAppearance="?textAppearanceBody1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/enter_number_phone_number" />
|
app:layout_constraintTop_toBottomOf="@+id/enter_number_page_headline" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/country_selection_box"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginStart="@dimen/keyline_5"
|
||||||
|
android:layout_marginTop="@dimen/keyline_4"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
|
android:background="@drawable/edit_text_black_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/select_country_or_region">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/country_name_code"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="@dimen/keyline_2"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:textAppearance="?textAppearanceBody1" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/national_flag"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_6"
|
||||||
|
android:src="@drawable/ic_list_country_au" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="6dp"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_4"
|
||||||
|
android:src="@drawable/ic_right" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/enter_number_headline"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/keyline_5"
|
||||||
|
android:layout_marginTop="@dimen/keyline_5"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/enter_number_headline"
|
||||||
|
android:textAppearance="?textAppearanceBody1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/country_selection_box" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/enter_number_phone_number"
|
android:id="@+id/enter_number_phone_number"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/text_field_height"
|
android:layout_height="@dimen/text_field_height"
|
||||||
android:layout_marginStart="@dimen/keyline_4"
|
android:layout_marginStart="@dimen/keyline_5"
|
||||||
android:layout_marginTop="@dimen/keyline_4"
|
android:layout_marginTop="@dimen/keyline_4"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
android:autofillHints="phoneNational"
|
android:autofillHints="phoneNational"
|
||||||
android:background="@drawable/edittext_modified_states"
|
android:background="@drawable/edittext_modified_states"
|
||||||
android:layout_marginEnd="@dimen/keyline_5"
|
android:digits="0123456789"
|
||||||
android:inputType="number|phone"
|
android:inputType="number|phone"
|
||||||
android:maxLength="10"
|
android:maxLength="20"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingStart="@dimen/keyline_1"
|
android:paddingStart="@dimen/keyline_1"
|
||||||
android:paddingEnd="@dimen/keyline_1"
|
android:paddingEnd="@dimen/keyline_1"
|
||||||
|
@ -55,63 +111,40 @@
|
||||||
android:textColorHighlight="@color/dark_cerulean_3"
|
android:textColorHighlight="@color/dark_cerulean_3"
|
||||||
android:textCursorDrawable="@null"
|
android:textCursorDrawable="@null"
|
||||||
android:textSize="@dimen/text_phone_number"
|
android:textSize="@dimen/text_phone_number"
|
||||||
android:digits="0123456789"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/enter_number_prefix"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/enter_number_headline"
|
app:layout_constraintTop_toBottomOf="@+id/enter_number_headline" />
|
||||||
tools:text="412382192" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
|
||||||
android:id="@+id/enter_number_barrier"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:barrierDirection="bottom"
|
|
||||||
app:constraint_referenced_ids="enter_number_prefix,enter_number_phone_number,invalid_phone_number" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/invalid_phone_number"
|
android:id="@+id/invalid_phone_number"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/keyline_1"
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
android:text="@string/invalid_phone_number"
|
android:text="@string/invalid_phone_number"
|
||||||
android:textColor="@color/error"
|
android:textColor="@color/error"
|
||||||
|
android:textSize="16sp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_marginStart="@dimen/keyline_5"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:layout_marginEnd="@dimen/keyline_5"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="@+id/enter_number_phone_number"
|
app:layout_constraintStart_toStartOf="@+id/enter_number_phone_number"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/enter_number_phone_number"
|
app:layout_constraintTop_toBottomOf="@+id/enter_number_phone_number"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
tools:text="@string/invalid_phone_number"
|
tools:text="@string/invalid_phone_number"
|
||||||
tools:visibility="visible"
|
tools:visibility="visible" />
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/use_oz_phone_number"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/keyline_4"
|
|
||||||
android:layout_marginStart="@dimen/keyline_5"
|
|
||||||
android:layout_marginEnd="@dimen/keyline_5"
|
|
||||||
android:text="@string/oz_phone_number"
|
|
||||||
android:textAppearance="?textAppearanceBody1"
|
|
||||||
android:textColorLink="?attr/colorPrimary"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/invalid_phone_number" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/enter_number_content"
|
android:id="@+id/enter_number_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/keyline_4"
|
|
||||||
android:layout_marginStart="@dimen/keyline_5"
|
android:layout_marginStart="@dimen/keyline_5"
|
||||||
|
android:layout_marginTop="@dimen/keyline_4"
|
||||||
android:layout_marginEnd="@dimen/keyline_5"
|
android:layout_marginEnd="@dimen/keyline_5"
|
||||||
android:text="@string/enter_number_content"
|
android:text="@string/enter_number_content"
|
||||||
tools:text="@string/enter_number_content"
|
|
||||||
android:textAppearance="?textAppearanceBody1"
|
android:textAppearance="?textAppearanceBody1"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/use_oz_phone_number" />
|
app:layout_constraintTop_toBottomOf="@+id/invalid_phone_number"
|
||||||
|
tools:text="@string/enter_number_content" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/enter_number_relativebackground"
|
android:id="@+id/enter_number_relativebackground"
|
||||||
|
@ -143,11 +176,11 @@
|
||||||
android:id="@+id/enter_number_relative"
|
android:id="@+id/enter_number_relative"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/keyline_1"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_4"
|
||||||
android:text="@string/enter_number_relative"
|
android:text="@string/enter_number_relative"
|
||||||
android:textAppearance="?textAppearanceBody2"
|
android:textAppearance="?textAppearanceBody2"
|
||||||
android:textColor="@color/slack_black"
|
android:textColor="@color/slack_black"
|
||||||
android:layout_marginStart="@dimen/keyline_1"
|
|
||||||
android:layout_marginEnd="@dimen/keyline_4"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/enter_number_relativebackground"
|
app:layout_constraintEnd_toEndOf="@+id/enter_number_relativebackground"
|
||||||
app:layout_constraintStart_toEndOf="@+id/enter_number_relative_icon"
|
app:layout_constraintStart_toEndOf="@+id/enter_number_relative_icon"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/enter_number_top_margin" />
|
app:layout_constraintTop_toBottomOf="@+id/enter_number_top_margin" />
|
||||||
|
|
|
@ -11,13 +11,14 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="@dimen/keyline_5"
|
android:paddingStart="@dimen/keyline_5"
|
||||||
android:paddingEnd="@dimen/keyline_5">
|
android:paddingEnd="@dimen/keyline_5"
|
||||||
|
android:paddingBottom="@dimen/keyline_9">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/personal_details_headline"
|
android:id="@+id/personal_details_headline"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/keyline_6"
|
android:layout_marginTop="@dimen/keyline_0"
|
||||||
android:text="@string/personal_details_headline"
|
android:text="@string/personal_details_headline"
|
||||||
android:contentDescription="@string/personal_details_headline_content_description"
|
android:contentDescription="@string/personal_details_headline_content_description"
|
||||||
android:textAppearance="?textAppearanceHeadline2"
|
android:textAppearance="?textAppearanceHeadline2"
|
||||||
|
@ -61,9 +62,9 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/personal_details_name_error"
|
android:id="@+id/personal_details_name_error"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/keyline_1"
|
android:layout_marginTop="@dimen/keyline_1"
|
||||||
android:text="@string/invalid_name"
|
android:text="@string/personal_details_name_error_prompt"
|
||||||
android:textColor="@color/error"
|
android:textColor="@color/error"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintStart_toEndOf="parent"
|
app:layout_constraintStart_toEndOf="parent"
|
||||||
|
@ -90,7 +91,7 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/personal_details_name_barrier" />
|
app:layout_constraintTop_toBottomOf="@+id/personal_details_name_barrier" />
|
||||||
|
|
||||||
<TextView
|
<EditText
|
||||||
android:id="@+id/personal_details_age"
|
android:id="@+id/personal_details_age"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/text_field_height"
|
android:layout_height="@dimen/text_field_height"
|
||||||
|
@ -114,9 +115,9 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/personal_details_age_error"
|
android:id="@+id/personal_details_age_error"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/keyline_1"
|
android:layout_marginTop="@dimen/keyline_1"
|
||||||
android:text="@string/invalid_age"
|
android:text="@string/personal_details_age_error_prompt"
|
||||||
android:textColor="@color/error"
|
android:textColor="@color/error"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintStart_toEndOf="parent"
|
app:layout_constraintStart_toEndOf="parent"
|
||||||
|
@ -169,15 +170,14 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/personal_details_post_code_error"
|
android:id="@+id/personal_details_post_code_error"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/keyline_1"
|
android:layout_marginTop="@dimen/keyline_1"
|
||||||
android:text="@string/invalid_post_code"
|
android:text="@string/personal_details_post_code_error_prompt"
|
||||||
android:textColor="@color/error"
|
android:textColor="@color/error"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintStart_toEndOf="parent"
|
app:layout_constraintStart_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/personal_details_post_code"
|
app:layout_constraintTop_toBottomOf="@+id/personal_details_post_code"
|
||||||
tools:text="@string/invalid_post_code"
|
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/permission_height"
|
android:layout_height="wrap_content"
|
||||||
tools:parentTag="android.widget.FrameLayout">
|
tools:parentTag="android.widget.FrameLayout">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
@ -12,30 +12,42 @@
|
||||||
android:background="?android:selectableItemBackground"
|
android:background="?android:selectableItemBackground"
|
||||||
android:padding="@dimen/keyline_4">
|
android:padding="@dimen/keyline_4">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/permission_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/icon_checkbox"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/permission_title"
|
android:id="@+id/permission_title"
|
||||||
style="?textAppearanceBody1"
|
style="?textAppearanceBody1"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:gravity="start|center_vertical"
|
android:gravity="start"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toLeftOf="@+id/permission_icon"
|
app:layout_constraintRight_toLeftOf="@+id/permission_icon"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="Bluetooth : " />
|
tools:text="Bluetooth : " />
|
||||||
|
|
||||||
<ImageView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/permission_icon"
|
android:id="@+id/permission_body"
|
||||||
android:layout_width="wrap_content"
|
style="?textAppearanceBody2"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/icon_checkbox"
|
android:gravity="start"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:paddingTop="@dimen/keyline_0"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
android:visibility="gone"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toBottomOf="@id/permission_title"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@+id/permission_icon"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:text="Allow push notification" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
44
app/src/main/res/layout/view_list_item_country.xml
Normal file
44
app/src/main/res/layout/view_list_item_country.xml
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/country_list_item"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="@dimen/keyline_4"
|
||||||
|
android:paddingTop="@dimen/keyline_1"
|
||||||
|
android:paddingBottom="@dimen/keyline_1">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/country_list_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="@dimen/keyline_5"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:lines="1"
|
||||||
|
android:gravity="start"
|
||||||
|
android:text="@string/country_au"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/country_list_flag"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/country_list_calling_code"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="21dp"
|
||||||
|
android:text="+61"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/country_list_name" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/country_list_flag"
|
||||||
|
android:layout_width="26dp"
|
||||||
|
android:layout_height="19dp"
|
||||||
|
android:layout_marginTop="@dimen/keyline_1"
|
||||||
|
android:layout_marginEnd="@dimen/keyline_8"
|
||||||
|
android:src="@drawable/ic_list_country_au"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/country_list_name" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/country_initial_letter"
|
||||||
|
style="@style/countryListIndex"
|
||||||
|
android:text="A" />
|
20
app/src/main/res/layout/view_list_item_group_title.xml
Normal file
20
app/src/main/res/layout/view_list_item_group_title.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#E5E5E5"
|
||||||
|
android:paddingLeft="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/country_group_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:text="@string/group_title_a"
|
||||||
|
android:textColor="#131313"
|
||||||
|
android:textSize="17sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<integer name="australian_phone_number_length">9</integer>
|
|
||||||
</resources>
|
|
|
@ -61,16 +61,16 @@
|
||||||
<string name="personal_details_headline_content_description">Heading, Enter your details</string>
|
<string name="personal_details_headline_content_description">Heading, Enter your details</string>
|
||||||
<string name="personal_details_name_title">Full name</string>
|
<string name="personal_details_name_title">Full name</string>
|
||||||
<string name="personal_details_name_content_description">Enter full name</string>
|
<string name="personal_details_name_content_description">Enter full name</string>
|
||||||
|
<string name="personal_details_name_error_prompt">Please enter your full name.</string>
|
||||||
<string name="personal_details_age_title">Age range (select)</string>
|
<string name="personal_details_age_title">Age range (select)</string>
|
||||||
<string name="personal_details_age_content_description">Select age range</string>
|
<string name="personal_details_age_content_description">Select age range</string>
|
||||||
<string name="personal_details_post_code">Postcode</string>
|
<string name="personal_details_age_error_prompt">Please select your age range.</string>
|
||||||
|
<string name="personal_details_post_code">Postcode in Australia</string>
|
||||||
<string name="personal_details_post_code_hint">e.g. 2000</string>
|
<string name="personal_details_post_code_hint">e.g. 2000</string>
|
||||||
<string name="personal_details_post_code_content_description">Enter postcode</string>
|
<string name="personal_details_post_code_content_description">Enter postcode</string>
|
||||||
|
<string name="personal_details_post_code_error_prompt">Your Australian postcode number must contain 4 digits. </string>
|
||||||
<string name="personal_details_disclaimer"><a href="https://www.health.gov.au/using-our-websites/privacy/privacy-notice-for-covidsafe-app">privacy policy</a></string>
|
<string name="personal_details_disclaimer"><a href="https://www.health.gov.au/using-our-websites/privacy/privacy-notice-for-covidsafe-app">privacy policy</a></string>
|
||||||
<string name="personal_details_post_code_dialog_title">Postcode</string>
|
<string name="personal_details_post_code_dialog_title">Postcode</string>
|
||||||
<string name="invalid_post_code">Invalid postcode</string>
|
|
||||||
<string name="invalid_age">Age cannot be empty</string>
|
|
||||||
<string name="invalid_name">Invalid name</string>
|
|
||||||
<string name="personal_details_age_dialog_title">Select your age</string>
|
<string name="personal_details_age_dialog_title">Select your age</string>
|
||||||
<string name="personal_details_dialog_ok">Select</string>
|
<string name="personal_details_dialog_ok">Select</string>
|
||||||
|
|
||||||
|
@ -98,13 +98,258 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- OnBoarding Enter Number -->
|
<!-- OnBoarding Enter Number -->
|
||||||
|
<string name="select_country_or_region">Select country or region</string>
|
||||||
<string name="enter_number_headline">Enter your mobile number</string>
|
<string name="enter_number_headline">Enter your mobile number</string>
|
||||||
|
<string name="enter_number_for_example">For example:</string>
|
||||||
<string name="invalid_phone_number">Invalid phone number.</string>
|
<string name="invalid_phone_number">Invalid phone number.</string>
|
||||||
<string name="enter_number_prefix">+61</string>
|
<string name="invalid_australian_phone_number_error_prompt">Australian mobile numbers contain a maximum of 10 digits.</string>
|
||||||
|
<string name="invalid_norfolk_island_phone_number_error_prompt">Mobile numbers in Norfolk Island contain 5 to 6 digits.</string>
|
||||||
|
<string name="invalid_phone_number_digits_error_prompt">Mobile numbers in %1s contain %2s digits.</string>
|
||||||
<string name="oz_phone_number"><a href="https://www.covidsafe.gov.au/help-topics.html#verify-mobile-number-pin">Use an Australian phone number.</a></string>
|
<string name="oz_phone_number"><a href="https://www.covidsafe.gov.au/help-topics.html#verify-mobile-number-pin">Use an Australian phone number.</a></string>
|
||||||
<string name="enter_number_content">We’ll send you a six-digit PIN to verify your mobile number.</string>
|
<string name="enter_number_content">We’ll send you a six-digit PIN to verify your mobile number.</string>
|
||||||
<string name="enter_number_relative">Trying to register on behalf of a friend or relative?\n\nThey will need to register using their own device and phone number so that COVIDSafe can work for them. </string>
|
<string name="enter_number_relative">Trying to register on behalf of a friend or relative?\n\nThey will need to register using their own device and phone number so that COVIDSafe can work for them. </string>
|
||||||
<string name="enter_number_button">Get PIN</string>
|
<string name="enter_number_button">Get PIN</string>
|
||||||
|
<string name="search">Search</string>
|
||||||
|
<string name="options_for_australia">Options for Australia</string>
|
||||||
|
<string name="group_title_a">A</string>
|
||||||
|
<string name="group_title_b">B</string>
|
||||||
|
<string name="group_title_c">C</string>
|
||||||
|
<string name="group_title_d">D</string>
|
||||||
|
<string name="group_title_e">E</string>
|
||||||
|
<string name="group_title_f">F</string>
|
||||||
|
<string name="group_title_g">G</string>
|
||||||
|
<string name="group_title_h">H</string>
|
||||||
|
<string name="group_title_i">I</string>
|
||||||
|
<string name="group_title_j">J</string>
|
||||||
|
<string name="group_title_k">K</string>
|
||||||
|
<string name="group_title_l">L</string>
|
||||||
|
<string name="group_title_m">M</string>
|
||||||
|
<string name="group_title_n">N</string>
|
||||||
|
<string name="group_title_o">O</string>
|
||||||
|
<string name="group_title_p">P</string>
|
||||||
|
<string name="group_title_q">Q</string>
|
||||||
|
<string name="group_title_r">R</string>
|
||||||
|
<string name="group_title_s">S</string>
|
||||||
|
<string name="group_title_t">T</string>
|
||||||
|
<string name="group_title_u">U</string>
|
||||||
|
<string name="group_title_v">V</string>
|
||||||
|
<string name="group_title_w">W</string>
|
||||||
|
<string name="group_title_x">X</string>
|
||||||
|
<string name="group_title_y">Y</string>
|
||||||
|
<string name="group_title_z">Z</string>
|
||||||
|
|
||||||
|
<!-- Countries -->
|
||||||
|
<string name="country_af">Afghanistan</string>
|
||||||
|
<string name="country_al">Albania</string>
|
||||||
|
<string name="country_dz">Algeria</string>
|
||||||
|
<string name="country_ad">Andorra</string>
|
||||||
|
<string name="country_ao">Angola</string>
|
||||||
|
<string name="country_ai">Anguilla</string>
|
||||||
|
<string name="country_ag">Antigua and Barbuda</string>
|
||||||
|
<string name="country_ar">Argentina</string>
|
||||||
|
<string name="country_am">Armenia</string>
|
||||||
|
<string name="country_aw">Aruba</string>
|
||||||
|
<string name="country_au">Australia</string>
|
||||||
|
<string name="country_at">Austria</string>
|
||||||
|
<string name="country_az">Azerbaijan</string>
|
||||||
|
<string name="country_bs">Bahamas</string>
|
||||||
|
<string name="country_bh">Bahrain</string>
|
||||||
|
<string name="country_bd">Bangladesh</string>
|
||||||
|
<string name="country_bb">Barbados</string>
|
||||||
|
<string name="country_by">Belarus</string>
|
||||||
|
<string name="country_be">Belgium</string>
|
||||||
|
<string name="country_bz">Belize</string>
|
||||||
|
<string name="country_bj">Benin</string>
|
||||||
|
<string name="country_bm">Bermuda</string>
|
||||||
|
<string name="country_bt">Bhutan</string>
|
||||||
|
<string name="country_bo">Bolivia</string>
|
||||||
|
<string name="country_ba">Bosnia and Herzegovina</string>
|
||||||
|
<string name="country_bw">Botswana</string>
|
||||||
|
<string name="country_br">Brazil</string>
|
||||||
|
<string name="country_bn">Brunei</string>
|
||||||
|
<string name="country_bg">Bulgaria</string>
|
||||||
|
<string name="country_bf">Burkina Faso</string>
|
||||||
|
<string name="country_bi">Burundi</string>
|
||||||
|
<string name="country_kh">Cambodia</string>
|
||||||
|
<string name="country_cm">Cameroon</string>
|
||||||
|
<string name="country_ca">Canada</string>
|
||||||
|
<string name="country_cv">Cape Verde</string>
|
||||||
|
<string name="country_ky">Cayman Islands</string>
|
||||||
|
<string name="country_cf">Central African Republic</string>
|
||||||
|
<string name="country_td">Chad</string>
|
||||||
|
<string name="country_cl">Chile</string>
|
||||||
|
<string name="country_cn">China</string>
|
||||||
|
<string name="country_co">Colombia</string>
|
||||||
|
<string name="country_km">Comoros</string>
|
||||||
|
<string name="country_ck">Cook Islands</string>
|
||||||
|
<string name="country_cr">Costa Rica</string>
|
||||||
|
<string name="country_hr">Croatia</string>
|
||||||
|
<string name="country_cu">Cuba</string>
|
||||||
|
<string name="country_cw">Curaçao</string>
|
||||||
|
<string name="country_cy">Cyprus</string>
|
||||||
|
<string name="country_cz">Czech Republic</string>
|
||||||
|
<string name="country_cd">Democratic Republic of the Congo</string>
|
||||||
|
<string name="country_dk">Denmark</string>
|
||||||
|
<string name="country_dj">Djibouti</string>
|
||||||
|
<string name="country_dm">Dominica</string>
|
||||||
|
<string name="country_do">Dominican Republic</string>
|
||||||
|
<string name="country_ec">Ecuador</string>
|
||||||
|
<string name="country_eg">Egypt</string>
|
||||||
|
<string name="country_sv">El Salvador</string>
|
||||||
|
<string name="country_gq">Equatorial Guinea</string>
|
||||||
|
<string name="country_ee">Estonia</string>
|
||||||
|
<string name="country_et">Ethiopia</string>
|
||||||
|
<string name="country_fo">Faroe Islands</string>
|
||||||
|
<string name="country_fj">Fiji</string>
|
||||||
|
<string name="country_fi">Finland</string>
|
||||||
|
<string name="country_fr">France</string>
|
||||||
|
<string name="country_gf">French Guiana</string>
|
||||||
|
<string name="country_ga">Gabon</string>
|
||||||
|
<string name="country_gm">Gambia</string>
|
||||||
|
<string name="country_ge">Georgia</string>
|
||||||
|
<string name="country_de">Germany</string>
|
||||||
|
<string name="country_gh">Ghana</string>
|
||||||
|
<string name="country_gi">Gibraltar</string>
|
||||||
|
<string name="country_gr">Greece</string>
|
||||||
|
<string name="country_gl">Greenland</string>
|
||||||
|
<string name="country_gd">Grenada</string>
|
||||||
|
<string name="country_gp">Guadeloupe</string>
|
||||||
|
<string name="country_gu">Guam</string>
|
||||||
|
<string name="country_gt">Guatemala</string>
|
||||||
|
<string name="country_gn">Guinea</string>
|
||||||
|
<string name="country_gw">Guinea-Bissau</string>
|
||||||
|
<string name="country_gy">Guyana</string>
|
||||||
|
<string name="country_ht">Haiti</string>
|
||||||
|
<string name="country_hn">Honduras</string>
|
||||||
|
<string name="country_hk">Hong Kong</string>
|
||||||
|
<string name="country_hu">Hungary</string>
|
||||||
|
<string name="country_is">Iceland</string>
|
||||||
|
<string name="country_in">India</string>
|
||||||
|
<string name="country_id">Indonesia</string>
|
||||||
|
<string name="country_ir">Iran</string>
|
||||||
|
<string name="country_iq">Iraq</string>
|
||||||
|
<string name="country_ie">Ireland</string>
|
||||||
|
<string name="country_il">Israel</string>
|
||||||
|
<string name="country_it">Italy</string>
|
||||||
|
<string name="country_ci">Ivory Coast</string>
|
||||||
|
<string name="country_jm">Jamaica</string>
|
||||||
|
<string name="country_jp">Japan</string>
|
||||||
|
<string name="country_jo">Jordan</string>
|
||||||
|
<string name="country_kz">Kazakhstan</string>
|
||||||
|
<string name="country_ke">Kenya</string>
|
||||||
|
<string name="country_ki">Kiribati</string>
|
||||||
|
<string name="country_kw">Kuwait</string>
|
||||||
|
<string name="country_kg">Kyrgyzstan</string>
|
||||||
|
<string name="country_la">Laos</string>
|
||||||
|
<string name="country_lv">Latvia</string>
|
||||||
|
<string name="country_lb">Lebanon</string>
|
||||||
|
<string name="country_ls">Lesotho</string>
|
||||||
|
<string name="country_lr">Liberia</string>
|
||||||
|
<string name="country_ly">Libya</string>
|
||||||
|
<string name="country_li">Liechtenstein</string>
|
||||||
|
<string name="country_lt">Lithuania</string>
|
||||||
|
<string name="country_lu">Luxembourg</string>
|
||||||
|
<string name="country_mo">Macau</string>
|
||||||
|
<string name="country_mk">North Macedonia</string>
|
||||||
|
<string name="country_mg">Madagascar</string>
|
||||||
|
<string name="country_mw">Malawi</string>
|
||||||
|
<string name="country_my">Malaysia</string>
|
||||||
|
<string name="country_mv">Maldives</string>
|
||||||
|
<string name="country_ml">Mali</string>
|
||||||
|
<string name="country_mt">Malta</string>
|
||||||
|
<string name="country_mq">Martinique</string>
|
||||||
|
<string name="country_mr">Mauritania</string>
|
||||||
|
<string name="country_mu">Mauritius</string>
|
||||||
|
<string name="country_mx">Mexico</string>
|
||||||
|
<string name="country_md">Moldova</string>
|
||||||
|
<string name="country_mc">Monaco</string>
|
||||||
|
<string name="country_mn">Mongolia</string>
|
||||||
|
<string name="country_me">Montenegro</string>
|
||||||
|
<string name="country_ms">Montserrat</string>
|
||||||
|
<string name="country_ma">Morocco</string>
|
||||||
|
<string name="country_mz">Mozambique</string>
|
||||||
|
<string name="country_mm">Myanmar</string>
|
||||||
|
<string name="country_na">Namibia</string>
|
||||||
|
<string name="country_np">Nepal</string>
|
||||||
|
<string name="country_nl">Netherlands</string>
|
||||||
|
<string name="country_an">Netherlands Antilles</string>
|
||||||
|
<string name="country_nc">New Caledonia</string>
|
||||||
|
<string name="country_nz">New Zealand</string>
|
||||||
|
<string name="country_ni">Nicaragua</string>
|
||||||
|
<string name="country_ne">Niger</string>
|
||||||
|
<string name="country_nf">Norfolk Island</string>
|
||||||
|
<string name="country_ng">Nigeria</string>
|
||||||
|
<string name="country_no">Norway</string>
|
||||||
|
<string name="country_om">Oman</string>
|
||||||
|
<string name="country_pk">Pakistan</string>
|
||||||
|
<string name="country_pw">Palau</string>
|
||||||
|
<string name="country_ps">Palestinian Territories</string>
|
||||||
|
<string name="country_pa">Panama</string>
|
||||||
|
<string name="country_pg">Papua New Guinea</string>
|
||||||
|
<string name="country_py">Paraguay</string>
|
||||||
|
<string name="country_pe">Peru</string>
|
||||||
|
<string name="country_ph">Philippines</string>
|
||||||
|
<string name="country_pl">Poland</string>
|
||||||
|
<string name="country_pt">Portugal</string>
|
||||||
|
<string name="country_pr">Puerto Rico</string>
|
||||||
|
<string name="country_qa">Qatar</string>
|
||||||
|
<string name="country_cg">Republic of the Congo</string>
|
||||||
|
<string name="country_re">Reunion Island</string>
|
||||||
|
<string name="country_ro">Romania</string>
|
||||||
|
<string name="country_ru">Russia</string>
|
||||||
|
<string name="country_rw">Rwanda</string>
|
||||||
|
<string name="country_kn">Saint Kitts and Nevis</string>
|
||||||
|
<string name="country_lc">Saint Lucia</string>
|
||||||
|
<string name="country_vc">Saint Vincent and the Grenadines</string>
|
||||||
|
<string name="country_ws">Samoa</string>
|
||||||
|
<string name="country_st">Sao Tome and Principe</string>
|
||||||
|
<string name="country_sa">Saudi Arabia</string>
|
||||||
|
<string name="country_sn">Senegal</string>
|
||||||
|
<string name="country_rs">Serbia</string>
|
||||||
|
<string name="country_sc">Seychelles</string>
|
||||||
|
<string name="country_sl">Sierra Leone</string>
|
||||||
|
<string name="country_sg">Singapore</string>
|
||||||
|
<string name="country_sk">Slovakia</string>
|
||||||
|
<string name="country_si">Slovenia</string>
|
||||||
|
<string name="country_sb">Solomon Islands</string>
|
||||||
|
<string name="country_so">Somalia</string>
|
||||||
|
<string name="country_za">South Africa</string>
|
||||||
|
<string name="country_kr">South Korea</string>
|
||||||
|
<string name="country_ss">South Sudan</string>
|
||||||
|
<string name="country_es">Spain</string>
|
||||||
|
<string name="country_lk">Sri Lanka</string>
|
||||||
|
<string name="country_sd">Sudan</string>
|
||||||
|
<string name="country_sr">Suriname</string>
|
||||||
|
<string name="country_sz">Swaziland</string>
|
||||||
|
<string name="country_se">Sweden</string>
|
||||||
|
<string name="country_ch">Switzerland</string>
|
||||||
|
<string name="country_tw">Taiwan</string>
|
||||||
|
<string name="country_tj">Tajikistan</string>
|
||||||
|
<string name="country_tz">Tanzania</string>
|
||||||
|
<string name="country_th">Thailand</string>
|
||||||
|
<string name="country_tl">Timor-Leste</string>
|
||||||
|
<string name="country_tg">Togo</string>
|
||||||
|
<string name="country_to">Tonga</string>
|
||||||
|
<string name="country_tt">Trinidad and Tobago</string>
|
||||||
|
<string name="country_tn">Tunisia</string>
|
||||||
|
<string name="country_tr">Turkey</string>
|
||||||
|
<string name="country_tm">Turkmenistan</string>
|
||||||
|
<string name="country_tc">Turks and Caicos Islands</string>
|
||||||
|
<string name="country_ug">Uganda</string>
|
||||||
|
<string name="country_ua">Ukraine</string>
|
||||||
|
<string name="country_ae">United Arab Emirates</string>
|
||||||
|
<string name="country_gb">United Kingdom</string>
|
||||||
|
<string name="country_us">United States</string>
|
||||||
|
<string name="country_uy">Uruguay</string>
|
||||||
|
<string name="country_uz">Uzbekistan</string>
|
||||||
|
<string name="country_vu">Vanuatu</string>
|
||||||
|
<string name="country_ve">Venezuela</string>
|
||||||
|
<string name="country_vn">Vietnam</string>
|
||||||
|
<string name="country_vg">British Virgin Islands</string>
|
||||||
|
<string name="country_vi">Virgin Islands, US</string>
|
||||||
|
<string name="country_ye">Yemen</string>
|
||||||
|
<string name="country_zm">Zambia</string>
|
||||||
|
<string name="country_zw">Zimbabwe</string>
|
||||||
|
|
||||||
<!-- OnBoarding Enter PIN -->
|
<!-- OnBoarding Enter PIN -->
|
||||||
<string name="enter_pin_headline">Enter the PIN sent to %s %s</string>
|
<string name="enter_pin_headline">Enter the PIN sent to %s %s</string>
|
||||||
|
@ -116,8 +361,8 @@
|
||||||
<string name="enter_pin_button">Verify</string>
|
<string name="enter_pin_button">Verify</string>
|
||||||
|
|
||||||
<!-- OnBoarding Permission -->
|
<!-- OnBoarding Permission -->
|
||||||
<string name="permission_headline">App permissions</string>
|
<string name="permission_headline">App settings</string>
|
||||||
<string name="permission_content">COVIDSafe needs Bluetooth® and notifications enabled to work.\n\nSelect ‘Proceed’ to:\n\n1. Enable Bluetooth®\n\n2. Allow Location permissions\n\n3. Disable Battery optimisation\n\n\nAndroid needs Location Permissions for Bluetooth® to work.\n\nCOVIDSafe does not send pairing requests.</string>
|
<string name="permission_content">COVIDSafe needs Bluetooth® and notifications enabled to work.\n\nSelect ‘Proceed’ to:\n\n1. Enable Bluetooth®\n\n2. Allow Location permissions\n\n3. Disable Battery optimisation\n\n\nAndroid needs Location permissions for Bluetooth® to work.\n\nCOVIDSafe does not send pairing requests.</string>
|
||||||
<string name="permission_button">Proceed</string>
|
<string name="permission_button">Proceed</string>
|
||||||
<string name="permission_location_rationale">Android requires location access to enable Bluetooth® functions for COVIDSafe. COVIDSafe cannot work properly without it</string>
|
<string name="permission_location_rationale">Android requires location access to enable Bluetooth® functions for COVIDSafe. COVIDSafe cannot work properly without it</string>
|
||||||
|
|
||||||
|
@ -143,25 +388,32 @@
|
||||||
<string name="permission_success_warning">Keep push notifications on for COVIDSafe so we can notify you quickly if the app isn\'t working properly.</string>
|
<string name="permission_success_warning">Keep push notifications on for COVIDSafe so we can notify you quickly if the app isn\'t working properly.</string>
|
||||||
<string name="permission_success_button">Continue</string>
|
<string name="permission_success_button">Continue</string>
|
||||||
|
|
||||||
|
<!-- Notifications -->
|
||||||
|
<string name="notification_active_title">COVIDSafe is active</string>
|
||||||
|
<string name="notification_not_active_title">COVIDSafe is not active</string>
|
||||||
|
<string name="notification_active_body">Keep COVIDSafe active when you leave home or are in public places.</string>
|
||||||
|
<string name="notification_not_active_body">Make sure COVIDSafe is active before you leave home or when in public places.</string>
|
||||||
|
|
||||||
<!-- Home -->
|
<!-- Home -->
|
||||||
<string name="home_header_active_title">COVIDSafe is active.</string>
|
<string name="home_header_active_title">COVIDSafe is active.</string>
|
||||||
<string name="home_header_active_no_action_required">No further action required.</string>
|
<string name="home_header_active_no_action_required">No further action required.</string>
|
||||||
<string name="home_header_inactive_title">COVIDSafe is not active.</string>
|
<string name="home_header_inactive_title">COVIDSafe is not active.</string>
|
||||||
<string name="home_header_inactive_check_your_permissions">Check your permissions.</string>
|
<string name="home_header_inactive_check_your_permissions">Check your settings.</string>
|
||||||
<string name="home_header_uploaded_on_date">Your information was uploaded on %s.</string>
|
<string name="home_header_uploaded_on_date">Your information was uploaded on %s.</string>
|
||||||
<string name="home_header_no_pairing">COVIDSafe does not send <a href="https://www.covidsafe.gov.au/help-topics.html#bluetooth-pairing-request">pairing requests</a>.</string>
|
<string name="home_header_no_pairing">COVIDSafe does not send <a href="https://www.covidsafe.gov.au/help-topics.html#bluetooth-pairing-request">pairing requests</a>.</string>
|
||||||
|
|
||||||
<string name="home_bluetooth_permission">Bluetooth®: %s</string>
|
<string name="home_bluetooth_permission">Bluetooth®: %s</string>
|
||||||
<string name="home_non_battery_optimization_permission">Battery optimization: %s</string>
|
<string name="home_non_battery_optimization_permission">Battery optimization: %s</string>
|
||||||
<string name="home_location_permission">Location: %s</string>
|
<string name="home_location_permission">Location: %s</string>
|
||||||
<string name="home_push_notification_permission">Push Notification: %s</string>
|
<string name="home_push_notification_permission">Push notification: %s</string>
|
||||||
<string name="home_permission_on">On</string>
|
<string name="home_permission_on">On</string>
|
||||||
<string name="home_permission_off">Off</string>
|
<string name="home_permission_off">Off</string>
|
||||||
<string name="home_setup_incomplete_title">Check\npermissions</string>
|
<string name="home_setup_incomplete_title">Check\npermissions</string>
|
||||||
<string name="home_setup_incomplete_subtitle">COVIDSafe needs permission to access these features.</string>
|
<string name="home_setup_incomplete_subtitle">COVIDSafe needs permission to access these features.</string>
|
||||||
<string name="home_setup_help">Help</string>
|
<string name="home_setup_help">Help</string>
|
||||||
<string name="home_app_permission_status_title">Check your permissions</string>
|
<string name="home_app_permission_status_title">Check your settings</string>
|
||||||
<string name="home_app_permission_status_subtitle">COVIDSafe won\'t work without these permissions. </string>
|
<string name="home_app_permission_status_subtitle">COVIDSafe won\'t work without the right settings. </string>
|
||||||
|
<string name="home_app_permission_push_notification_prompt">Allow COVIDSafe to push notifications.</string>
|
||||||
<string name="home_been_tested_title">Has a health official asked you to upload your data?</string>
|
<string name="home_been_tested_title">Has a health official asked you to upload your data?</string>
|
||||||
<string name="home_data_uploaded">Register for self isolation</string>
|
<string name="home_data_uploaded">Register for self isolation</string>
|
||||||
<string name="home_data_uploaded_message">Help stop the spread of COVID-19 and track your symptoms.</string>
|
<string name="home_data_uploaded_message">Help stop the spread of COVID-19 and track your symptoms.</string>
|
||||||
|
@ -197,7 +449,7 @@
|
||||||
<string name="upload_step_1_header_content_description">Heading, Is a health official asking you to upload your information?</string>
|
<string name="upload_step_1_header_content_description">Heading, Is a health official asking you to upload your information?</string>
|
||||||
<string name="upload_step_1_body">Only if you test positive to COVID-19 will a state or territory health official contact you to assist with voluntary upload of your information.\n\nOnce you press ‘Yes’ you’ll need to provide consent to upload your information. </string>
|
<string name="upload_step_1_body">Only if you test positive to COVID-19 will a state or territory health official contact you to assist with voluntary upload of your information.\n\nOnce you press ‘Yes’ you’ll need to provide consent to upload your information. </string>
|
||||||
|
|
||||||
<string name="upload_step_4_header">Upload consent</string>
|
<string name="upload_step_4_header"> Upload consent</string>
|
||||||
<string name="upload_step_4_header_content_description">Heading, Upload consent</string>
|
<string name="upload_step_4_header_content_description">Heading, Upload consent</string>
|
||||||
<string name="upload_step_4_sub_header">Unless you consent, your close contact information will not be uploaded.\n\nIf you consent, your close contact information will be uploaded and shared with state or territory health officials for contact tracing purposes.\n\nRead the COVIDSafe <a href="https://www.health.gov.au/using-our-websites/privacy/privacy-notice-for-covidsafe-app">privacy policy</a> for further details.</string>
|
<string name="upload_step_4_sub_header">Unless you consent, your close contact information will not be uploaded.\n\nIf you consent, your close contact information will be uploaded and shared with state or territory health officials for contact tracing purposes.\n\nRead the COVIDSafe <a href="https://www.health.gov.au/using-our-websites/privacy/privacy-notice-for-covidsafe-app">privacy policy</a> for further details.</string>
|
||||||
<string name="upload_step_verify_pin_header">Upload your information</string>
|
<string name="upload_step_verify_pin_header">Upload your information</string>
|
||||||
|
@ -224,4 +476,5 @@
|
||||||
<string name="activity_self_isolation_headline">Thank you! You have helped to stop the spread of COVID-19!</string>
|
<string name="activity_self_isolation_headline">Thank you! You have helped to stop the spread of COVID-19!</string>
|
||||||
<string name="activity_self_isolation_content">You’ve kept others safe while helping to stop the spread of COVID-19 during self-isolation.</string>
|
<string name="activity_self_isolation_content">You’ve kept others safe while helping to stop the spread of COVID-19 during self-isolation.</string>
|
||||||
<string name="activity_self_isolation_button">Continue</string>
|
<string name="activity_self_isolation_button">Continue</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -32,4 +32,12 @@
|
||||||
<item name="android:fontFamily">@font/font_roboto_regular</item>
|
<item name="android:fontFamily">@font/font_roboto_regular</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="countryListIndex">
|
||||||
|
<item name="android:textColor">@color/dark_green</item>
|
||||||
|
<item name="android:textSize">13sp</item>
|
||||||
|
<item name="android:layout_width">@dimen/keyline_8</item>
|
||||||
|
<item name="android:gravity">center</item>
|
||||||
|
<item name="android:layout_height">18dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -12,7 +12,7 @@ buildscript {
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.3'
|
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
@ -25,6 +25,7 @@ allprojects {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
|
maven { url "https://dl.bintray.com/mikefot/maven/" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
security.txt
21
security.txt
|
@ -1,17 +1,20 @@
|
||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
Hash: SHA256
|
Hash: SHA256
|
||||||
|
|
||||||
Contact: mailto:support@covidsafe.gov.au
|
Contact: mailto:security@covidsafe.gov.au
|
||||||
Canonical: https://www.covidsafe.gov.au/.well-known/security.txt
|
Canonical: https://www.covidsafe.gov.au/.well-known/security.txt
|
||||||
Encryption: https://www.covidsafe.gov.au/.well-known/pgp-key.txt
|
Encryption: https://www.covidsafe.gov.au/.well-known/pgp-key.txt
|
||||||
-----BEGIN PGP SIGNATURE-----
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
iQFNBAEBCAA3FiEEbUgetBuPAas8w7zHDyQUNNekxBkFAl6xF6AZHHN1cHBvcnRA
|
iQHOBAEBCAA4FiEEUWgkqhSOHRHwGue2IZjqt5flXH4FAl7Hkw0aHHNlY3VyaXR5
|
||||||
Y292aWRzYWZlLmdvdi5hdQAKCRAPJBQ016TEGd+bCACLrYjCbKRsTsQQyZVVtGxj
|
QGNvdmlkc2FmZS5nb3YuYXUACgkQIZjqt5flXH4KfQv/ZagXzgn9HspSTupO7zQQ
|
||||||
wYKW2AWclnKZWX/sxnTexg6D1tlGbZbB0OJpw0gJ0NpMoOLFd0kRZXOzv8RocIdx
|
t7lpZsNWKJsXddUD3+JQQ8b1uB9kmHhiydIXervEc1yGti6YYZxKybehLdvv7HjV
|
||||||
xd90Nwwl3NQ2ygGCDXR0Y7uRKX/P/Y1xO7XkyiYXAqVq3YWvI9M04pY/TCRvRZ/1
|
Cps9kn3cns9ex3s+KEMMFrU7MykvZ2x+fvCoGfgzWm1UJElxn/cSbOnt38VxmSjC
|
||||||
qBs/WDHv/6eRh2qNy/WGXD66CmTLHBcXilTeihcTZ/27Mny5SPthdfy8odQnhUja
|
wkmh+DGa1z9OB6ZMuivO2XBx+Y0GV5tsoxWKRtXMruQ41bTHZvIJ9lJctYTv2xEK
|
||||||
NfFxDm+8gQuFKUUQmr9rd8FEMPSl6BWf/kQtn0YmTeZRzD01uT1ydeHkyPSgn+nq
|
hYlHmrzkZjLM/sTwGKWj+ARCn1IA0Zp8uxkoBi3/++NonKAlQpSZ4Rk6B780H8GM
|
||||||
k9us35AlkI7aZNfNkFVWJ2v5ZVAdTHDh3pgBRZETwVg1of5DEXhc5XJV6mLsu9bM
|
5lCZVLIRfH1VJzPr7+eSSBF8p0coEapyO7bk/ioBIQB5v4xfvpJRBEc+eI7IZeDa
|
||||||
=tik2
|
TcO/TVZw7Vut89flR+34g9PCSFDCJgv5zR8vE5mB5m/vlfJ7XI99XMwvFNWgpcyL
|
||||||
|
72tFv74uH6tUPZOlbHGZTnBsQLkuj4fwUYaUPcR9TzeMlBHoe21bQ6OeDO02rIy4
|
||||||
|
09bWSTMGe33LvTz2UMuEkZcsNT8vc7J+597GSxgDWoR6
|
||||||
|
=6MOG
|
||||||
-----END PGP SIGNATURE-----
|
-----END PGP SIGNATURE-----
|
||||||
|
|
Loading…
Reference in a new issue