@@ -44,12 +44,12 @@ class ReactNativeAlertModule(
4444 if (dialogRef.get()?.isShowing == true ) {
4545 return
4646 }
47-
47+
4848 val activity = currentActivity ? : return
49- if (activity.isFinishing || ( Build . VERSION . SDK_INT >= 17 && activity.isDestroyed) ) return
49+ if (activity.isFinishing || activity.isDestroyed) return
5050
5151 UiThreadUtil .runOnUiThread {
52- if (activity.isFinishing || ( Build . VERSION . SDK_INT >= 17 && activity.isDestroyed) ) return @runOnUiThread
52+ if (activity.isFinishing || activity.isDestroyed) return @runOnUiThread
5353
5454 val themed: Context = if (Build .VERSION .SDK_INT >= 29 ) {
5555 // Use system theme on Android 10+ (API 29+)
@@ -75,19 +75,34 @@ class ReactNativeAlertModule(
7575 labels.getOrNull(0 )?.let { text ->
7676 builder.setNeutralButton(text) { _, _ ->
7777 dialogRef.clear()
78- onAction.invoke(0 /* buttonClicked*/ , 0 /* neutral*/ , mainInput?.text?.toString(), usernameInput?.text?.toString())
78+ onAction.invoke(
79+ 0 /* buttonClicked*/ ,
80+ 0 /* neutral*/ ,
81+ mainInput?.text?.toString(),
82+ usernameInput?.text?.toString()
83+ )
7984 }
8085 }
8186 labels.getOrNull(1 )?.let { text ->
8287 builder.setNegativeButton(text) { _, _ ->
8388 dialogRef.clear()
84- onAction.invoke(0 , 1 /* negative*/ , mainInput?.text?.toString(), usernameInput?.text?.toString())
89+ onAction.invoke(
90+ 0 ,
91+ 1 /* negative*/ ,
92+ mainInput?.text?.toString(),
93+ usernameInput?.text?.toString()
94+ )
8595 }
8696 }
8797 labels.getOrNull(2 )?.let { text ->
8898 builder.setPositiveButton(text) { _, _ ->
8999 dialogRef.clear()
90- onAction.invoke(0 , 2 /* positive*/ , mainInput?.text?.toString(), usernameInput?.text?.toString())
100+ onAction.invoke(
101+ 0 ,
102+ 2 /* positive*/ ,
103+ mainInput?.text?.toString(),
104+ usernameInput?.text?.toString()
105+ )
91106 }
92107 }
93108
@@ -98,12 +113,12 @@ class ReactNativeAlertModule(
98113
99114 val dialog = builder.create()
100115 dialogRef = WeakReference (dialog)
101-
116+
102117 // Set window soft input mode to show keyboard
103118 dialog.window?.setSoftInputMode(WindowManager .LayoutParams .SOFT_INPUT_STATE_VISIBLE )
104-
119+
105120 dialog.show()
106-
121+
107122 // Show keyboard after dialog is shown
108123 val firstInput = usernameInput ? : mainInput
109124 firstInput?.let { input ->
@@ -125,19 +140,38 @@ class ReactNativeAlertModule(
125140 }
126141
127142 // ----- Helpers -----
143+ private val Int .dp: Int
144+ get() = (this * android.content.res.Resources .getSystem().displayMetrics.density).toInt()
145+
146+ private fun Context.getThemeColor (attr : Int ): Int {
147+ val typedArray = obtainStyledAttributes(intArrayOf(attr))
148+ val color = typedArray.getColor(0 , 0xFF000000 .toInt())
149+ typedArray.recycle()
150+ return color
151+ }
152+
153+ private data class InputViews (
154+ val contentView : LinearLayout ? ,
155+ val usernameInput : EditText ? ,
156+ val mainInput : EditText ?
157+ )
158+
128159 private fun buildInputs (
129160 ctx : Context ,
130161 type : String ,
131162 config : ReadableMap
132- ): Triple < LinearLayout ?, EditText ?, EditText ?> {
133- if (type == " default" ) return Triple (null , null , null )
163+ ): InputViews {
164+ if (type == " default" ) return InputViews (null , null , null )
134165
135166 val layout = LinearLayout (ctx).apply {
136167 orientation = LinearLayout .VERTICAL
137- val horizontalPad = (ctx.resources.displayMetrics.density * 20 ).toInt()
138- val verticalPad = (ctx.resources.displayMetrics.density * 12 ).toInt()
168+ val horizontalPad = 20 .dp
169+ val verticalPad = 12 .dp
139170 setPadding(horizontalPad, verticalPad, horizontalPad, verticalPad)
140- layoutParams = ViewGroup .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .WRAP_CONTENT )
171+ layoutParams = ViewGroup .LayoutParams (
172+ ViewGroup .LayoutParams .MATCH_PARENT ,
173+ ViewGroup .LayoutParams .WRAP_CONTENT
174+ )
141175 }
142176
143177 val isLogin = type == " login-password"
@@ -148,11 +182,9 @@ class ReactNativeAlertModule(
148182 config.getIntOrNull(" usernameMaxLength" )?.takeIf { it > 0 }?.let {
149183 filters = arrayOf(InputFilter .LengthFilter (it))
150184 }
151- val typedArray = ctx.obtainStyledAttributes(intArrayOf(android.R .attr.colorControlNormal))
152- val tintColor = typedArray.getColor(0 , 0xFF000000 .toInt())
153- typedArray.recycle()
185+ val tintColor = ctx.getThemeColor(android.R .attr.colorControlNormal)
154186 backgroundTintList = android.content.res.ColorStateList .valueOf(tintColor)
155- val margin = (ctx.resources.displayMetrics.density * 4 ).toInt()
187+ val margin = 4 .dp
156188 val params = LinearLayout .LayoutParams (
157189 LinearLayout .LayoutParams .MATCH_PARENT ,
158190 LinearLayout .LayoutParams .WRAP_CONTENT
@@ -174,9 +206,7 @@ class ReactNativeAlertModule(
174206 filters = arrayOf(InputFilter .LengthFilter (it))
175207 }
176208 // Apply theme-aware background tint
177- val typedArray = ctx.obtainStyledAttributes(intArrayOf(android.R .attr.colorControlNormal))
178- val tintColor = typedArray.getColor(0 , 0xFF000000 .toInt())
179- typedArray.recycle()
209+ val tintColor = ctx.getThemeColor(android.R .attr.colorControlNormal)
180210 backgroundTintList = android.content.res.ColorStateList .valueOf(tintColor)
181211 layoutParams = LinearLayout .LayoutParams (
182212 LinearLayout .LayoutParams .MATCH_PARENT ,
@@ -188,17 +218,23 @@ class ReactNativeAlertModule(
188218 applyKeyboardType(username ? : main, config.getStringOrNull(" keyboardType" ))
189219
190220 layout.addView(main)
191- return Triple (layout, username, main)
221+ return InputViews (layout, username, main)
192222 }
193223
194224 private fun applyKeyboardType (target : EditText , keyboardType : String? ) {
195225 when (keyboardType) {
196- " email-address" -> target.inputType = InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_VARIATION_EMAIL_ADDRESS
226+ " email-address" -> target.inputType =
227+ InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_VARIATION_EMAIL_ADDRESS
228+
197229 " numeric" , " number-pad" -> target.inputType = InputType .TYPE_CLASS_NUMBER
198230 " phone-pad" -> target.inputType = InputType .TYPE_CLASS_PHONE
199- " decimal-pad" -> target.inputType = InputType .TYPE_CLASS_NUMBER or InputType .TYPE_NUMBER_FLAG_DECIMAL
231+ " decimal-pad" -> target.inputType =
232+ InputType .TYPE_CLASS_NUMBER or InputType .TYPE_NUMBER_FLAG_DECIMAL
233+
200234 " url" -> target.inputType = InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_VARIATION_URI
201- " web-search" , " twitter" -> target.inputType = InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
235+ " web-search" , " twitter" -> target.inputType =
236+ InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
237+
202238 else -> Unit
203239 }
204240 }
@@ -214,7 +250,8 @@ class ReactNativeAlertModule(
214250 if (hasKey(key) && ! isNull(key)) getInt(key) else null
215251
216252 private fun ReadableMap.getArrayOrEmpty (key : String ): ReadableArray =
217- if (hasKey(key) && ! isNull(key)) getArray(key) ? : Arguments .createArray() else Arguments .createArray()
253+ if (hasKey(key) && ! isNull(key)) getArray(key)
254+ ? : Arguments .createArray() else Arguments .createArray()
218255
219256 private fun ReadableArray.collectButtonLabels (max : Int ): List <String > {
220257 val out = ArrayList <String >(max)
0 commit comments