15
15
16
16
package com.amplifyframework.ui.authenticator.strings
17
17
18
+ import android.annotation.SuppressLint
18
19
import androidx.compose.runtime.Composable
19
20
import androidx.compose.runtime.ReadOnlyComposable
20
- import androidx.compose.ui.ExperimentalComposeUiApi
21
+ import androidx.compose.ui.platform.LocalContext
21
22
import androidx.compose.ui.res.pluralStringResource
22
23
import androidx.compose.ui.res.stringResource
23
24
import com.amplifyframework.auth.AuthException
@@ -27,8 +28,13 @@ import com.amplifyframework.ui.authenticator.forms.FieldError
27
28
import com.amplifyframework.ui.authenticator.forms.FieldKey
28
29
import com.amplifyframework.ui.authenticator.forms.PasswordError
29
30
import com.amplifyframework.ui.authenticator.locals.LocalStringResolver
31
+ import com.amplifyframework.ui.authenticator.util.toResourceName
32
+ import kotlin.reflect.KClass
30
33
31
34
internal open class StringResolver {
35
+ // Avoid recomputing the same error message for each type of exception
36
+ private val cachedErrorMessages = mutableMapOf<KClass <out AuthException >, String > ()
37
+
32
38
@Composable
33
39
@ReadOnlyComposable
34
40
open fun label (config : FieldConfig ): String {
@@ -41,54 +47,49 @@ internal open class StringResolver {
41
47
42
48
@Composable
43
49
@ReadOnlyComposable
44
- private fun title (config : FieldConfig ): String {
45
- return config.label ? : when (config.key) {
46
- FieldKey .ConfirmPassword -> stringResource(R .string.amplify_ui_authenticator_field_label_password_confirm)
47
- FieldKey .ConfirmationCode -> stringResource(R .string.amplify_ui_authenticator_field_label_confirmation_code)
48
- FieldKey .Password -> stringResource(R .string.amplify_ui_authenticator_field_label_password)
49
- FieldKey .PhoneNumber -> stringResource(R .string.amplify_ui_authenticator_field_label_phone_number)
50
- FieldKey .Email -> stringResource(R .string.amplify_ui_authenticator_field_label_email)
51
- FieldKey .Username -> stringResource(R .string.amplify_ui_authenticator_field_label_username)
52
- FieldKey .Birthdate -> stringResource(R .string.amplify_ui_authenticator_field_label_birthdate)
53
- FieldKey .FamilyName -> stringResource(R .string.amplify_ui_authenticator_field_label_family_name)
54
- FieldKey .GivenName -> stringResource(R .string.amplify_ui_authenticator_field_label_given_name)
55
- FieldKey .MiddleName -> stringResource(R .string.amplify_ui_authenticator_field_label_middle_name)
56
- FieldKey .Name -> stringResource(R .string.amplify_ui_authenticator_field_label_name)
57
- FieldKey .Website -> stringResource(R .string.amplify_ui_authenticator_field_label_website)
58
- FieldKey .PhoneNumber -> stringResource(R .string.amplify_ui_authenticator_field_label_phone_number)
59
- FieldKey .Nickname -> stringResource(R .string.amplify_ui_authenticator_field_label_nickname)
60
- FieldKey .PreferredUsername ->
61
- stringResource(R .string.amplify_ui_authenticator_field_label_preferred_username)
62
- FieldKey .Profile -> stringResource(R .string.amplify_ui_authenticator_field_label_profile)
63
- FieldKey .VerificationAttribute ->
64
- stringResource(R .string.amplify_ui_authenticator_field_label_verification_attribute)
65
- else -> " "
66
- }
50
+ private fun title (config : FieldConfig ): String = config.label ? : when (config.key) {
51
+ FieldKey .ConfirmPassword -> stringResource(R .string.amplify_ui_authenticator_field_label_password_confirm)
52
+ FieldKey .ConfirmationCode -> stringResource(R .string.amplify_ui_authenticator_field_label_confirmation_code)
53
+ FieldKey .Password -> stringResource(R .string.amplify_ui_authenticator_field_label_password)
54
+ FieldKey .PhoneNumber -> stringResource(R .string.amplify_ui_authenticator_field_label_phone_number)
55
+ FieldKey .Email -> stringResource(R .string.amplify_ui_authenticator_field_label_email)
56
+ FieldKey .Username -> stringResource(R .string.amplify_ui_authenticator_field_label_username)
57
+ FieldKey .Birthdate -> stringResource(R .string.amplify_ui_authenticator_field_label_birthdate)
58
+ FieldKey .FamilyName -> stringResource(R .string.amplify_ui_authenticator_field_label_family_name)
59
+ FieldKey .GivenName -> stringResource(R .string.amplify_ui_authenticator_field_label_given_name)
60
+ FieldKey .MiddleName -> stringResource(R .string.amplify_ui_authenticator_field_label_middle_name)
61
+ FieldKey .Name -> stringResource(R .string.amplify_ui_authenticator_field_label_name)
62
+ FieldKey .Website -> stringResource(R .string.amplify_ui_authenticator_field_label_website)
63
+ FieldKey .PhoneNumber -> stringResource(R .string.amplify_ui_authenticator_field_label_phone_number)
64
+ FieldKey .Nickname -> stringResource(R .string.amplify_ui_authenticator_field_label_nickname)
65
+ FieldKey .PreferredUsername ->
66
+ stringResource(R .string.amplify_ui_authenticator_field_label_preferred_username)
67
+ FieldKey .Profile -> stringResource(R .string.amplify_ui_authenticator_field_label_profile)
68
+ FieldKey .VerificationAttribute ->
69
+ stringResource(R .string.amplify_ui_authenticator_field_label_verification_attribute)
70
+ else -> " "
67
71
}
68
72
69
73
@Composable
70
74
@ReadOnlyComposable
71
- open fun hint (config : FieldConfig ): String? {
72
- return config.hint ? : when {
73
- config.key == FieldKey .ConfirmPassword ->
74
- stringResource(R .string.amplify_ui_authenticator_field_hint_password_confirm)
75
- config is FieldConfig .Date -> " yyyy-mm-dd"
76
- else -> {
77
- val label = label(config)
78
- stringResource(R .string.amplify_ui_authenticator_field_hint, label)
79
- }
75
+ open fun hint (config : FieldConfig ): String? = config.hint ? : when {
76
+ config.key == FieldKey .ConfirmPassword ->
77
+ stringResource(R .string.amplify_ui_authenticator_field_hint_password_confirm)
78
+ config is FieldConfig .Date -> " yyyy-mm-dd"
79
+ else -> {
80
+ val label = label(config)
81
+ stringResource(R .string.amplify_ui_authenticator_field_hint, label)
80
82
}
81
83
}
82
84
83
- @OptIn(ExperimentalComposeUiApi ::class )
84
85
@Composable
85
86
@ReadOnlyComposable
86
- open fun error (config : FieldConfig , error : FieldError ): String {
87
- return when (error) {
88
- is FieldError . InvalidPassword -> {
89
- var errorText = stringResource( R .string.amplify_ui_authenticator_field_password_requirements)
90
- error.errors.forEach {
91
- errorText + = " \n " + when (it) {
87
+ open fun error (config : FieldConfig , error : FieldError ): String = when (error) {
88
+ is FieldError . InvalidPassword -> {
89
+ var errorText = stringResource( R .string.amplify_ui_authenticator_field_password_requirements)
90
+ error.errors.forEach {
91
+ errorText + = " \n " +
92
+ when (it) {
92
93
is PasswordError .InvalidPasswordLength ->
93
94
pluralStringResource(
94
95
id = R .plurals.amplify_ui_authenticator_field_password_too_short,
@@ -105,54 +106,57 @@ internal open class StringResolver {
105
106
stringResource(R .string.amplify_ui_authenticator_field_password_missing_lower)
106
107
else -> " "
107
108
}
108
- }
109
- errorText
110
- }
111
- FieldError .PasswordsDoNotMatch ->
112
- stringResource(R .string.amplify_ui_authenticator_field_warn_unmatched_password)
113
- FieldError .MissingRequired -> {
114
- val label = title(config)
115
- stringResource(R .string.amplify_ui_authenticator_field_warn_empty, label)
116
- }
117
- FieldError .InvalidFormat -> {
118
- val label = title(config)
119
- stringResource(R .string.amplify_ui_authenticator_field_warn_invalid_format, label)
120
- }
121
- FieldError .FieldValueExists -> {
122
- val label = title(config)
123
- stringResource(R .string.amplify_ui_authenticator_field_warn_existing, label)
124
- }
125
- FieldError .ConfirmationCodeIncorrect -> {
126
- stringResource(R .string.amplify_ui_authenticator_field_warn_incorrect_code)
127
109
}
128
- is FieldError .Custom -> error.message
129
- FieldError .NotFound -> {
130
- val label = title(config)
131
- stringResource(R .string.amplify_ui_authenticator_field_warn_not_found, label)
132
- }
133
- else -> " "
110
+ errorText
111
+ }
112
+ FieldError .PasswordsDoNotMatch ->
113
+ stringResource(R .string.amplify_ui_authenticator_field_warn_unmatched_password)
114
+ FieldError .MissingRequired -> {
115
+ val label = title(config)
116
+ stringResource(R .string.amplify_ui_authenticator_field_warn_empty, label)
117
+ }
118
+ FieldError .InvalidFormat -> {
119
+ val label = title(config)
120
+ stringResource(R .string.amplify_ui_authenticator_field_warn_invalid_format, label)
121
+ }
122
+ FieldError .FieldValueExists -> {
123
+ val label = title(config)
124
+ stringResource(R .string.amplify_ui_authenticator_field_warn_existing, label)
125
+ }
126
+ FieldError .ConfirmationCodeIncorrect -> {
127
+ stringResource(R .string.amplify_ui_authenticator_field_warn_incorrect_code)
128
+ }
129
+ is FieldError .Custom -> error.message
130
+ FieldError .NotFound -> {
131
+ val label = title(config)
132
+ stringResource(R .string.amplify_ui_authenticator_field_warn_not_found, label)
134
133
}
134
+ else -> " "
135
135
}
136
136
137
- @Suppress( " UNUSED_EXPRESSION " )
137
+ @SuppressLint( " DiscouragedApi " )
138
138
@Composable
139
139
@ReadOnlyComposable
140
140
open fun error (error : AuthException ): String {
141
- return when (error) {
142
- else -> stringResource(R .string.amplify_ui_authenticator_error_unknown)
141
+ val context = LocalContext .current
142
+ return cachedErrorMessages.getOrPut(error::class ) {
143
+ // Check if the customer application has defined a specific string for this Exception type. If not, return
144
+ // the generic error message.
145
+ val resourceName = error.toResourceName()
146
+ val resourceId = context.resources.getIdentifier(resourceName, " string" , context.packageName)
147
+ val message = if (resourceId != 0 ) stringResource(resourceId) else null
148
+ message ? : stringResource(R .string.amplify_ui_authenticator_error_unknown)
143
149
}
144
150
}
145
151
146
152
companion object {
147
153
@Composable
148
154
@ReadOnlyComposable
149
- fun label (config : FieldConfig ) =
150
- LocalStringResolver .current.label(config = config)
155
+ fun label (config : FieldConfig ) = LocalStringResolver .current.label(config = config)
151
156
152
157
@Composable
153
158
@ReadOnlyComposable
154
- fun hint (config : FieldConfig ) =
155
- LocalStringResolver .current.hint(config = config)
159
+ fun hint (config : FieldConfig ) = LocalStringResolver .current.hint(config = config)
156
160
157
161
@Composable
158
162
@ReadOnlyComposable
@@ -161,7 +165,6 @@ internal open class StringResolver {
161
165
162
166
@Composable
163
167
@ReadOnlyComposable
164
- fun error (error : AuthException ) =
165
- LocalStringResolver .current.error(error = error)
168
+ fun error (error : AuthException ) = LocalStringResolver .current.error(error = error)
166
169
}
167
170
}
0 commit comments