11package com.parishod.watomatic.activity.login
22
3+ import android.app.AlertDialog
34import android.content.Intent
45import android.os.Bundle
56import android.text.Editable
@@ -11,11 +12,14 @@ import androidx.activity.result.contract.ActivityResultContracts
1112import androidx.core.view.ViewCompat
1213import androidx.core.view.WindowInsetsCompat
1314import com.google.android.gms.auth.api.signin.GoogleSignIn
15+ import com.google.android.gms.auth.api.signin.GoogleSignInAccount
1416import com.google.android.gms.auth.api.signin.GoogleSignInClient
1517import com.google.android.gms.auth.api.signin.GoogleSignInOptions
1618import com.google.android.gms.common.SignInButton
1719import com.google.android.gms.common.api.ApiException
20+ import com.google.android.gms.tasks.Task
1821import com.google.firebase.auth.FirebaseAuth
22+ import com.google.firebase.auth.FirebaseUser
1923import com.google.firebase.auth.GoogleAuthProvider
2024import com.parishod.watomatic.R
2125import com.parishod.watomatic.activity.BaseActivity
@@ -30,6 +34,12 @@ class LoginActivity : BaseActivity() {
3034 private lateinit var auth: FirebaseAuth
3135 private lateinit var googleSignInLauncher: ActivityResultLauncher <Intent >
3236
37+ companion object {
38+ private const val PREF_USER_EMAIL = " pref_user_email"
39+ private const val EMAIL_ALREADY_EXISTS = " email address is already"
40+ private const val INVALID_CREDENTIALS = " credential is incorrect"
41+ }
42+
3343 override fun onCreate (savedInstanceState : Bundle ? ) {
3444 super .onCreate(savedInstanceState)
3545 binding = ActivityLoginBinding .inflate(layoutInflater)
@@ -56,37 +66,34 @@ class LoginActivity : BaseActivity() {
5666
5767 googleSignInClient = GoogleSignIn .getClient(this , gso)
5868
59- googleSignInLauncher = registerForActivityResult(
60- ActivityResultContracts .StartActivityForResult ()
61- ) { result ->
69+ googleSignInLauncher = registerForActivityResult(ActivityResultContracts .StartActivityForResult ()) { result ->
6270 if (result.resultCode == RESULT_OK ) {
6371 val task = GoogleSignIn .getSignedInAccountFromIntent(result.data)
64- try {
65- val account = task.getResult(ApiException ::class .java)
66- account.idToken?.let { firebaseAuthWithGoogle(it) }
67- } catch (e: ApiException ) {
68- Toast .makeText(this , " Google sign in failed: ${e.message} " , Toast .LENGTH_SHORT ).show()
69- }
72+ handleGoogleSignInResult(task)
7073 }
7174 }
7275 }
7376
77+ private fun handleGoogleSignInResult (completedTask : Task <GoogleSignInAccount >) {
78+ try {
79+ val account = completedTask.getResult(ApiException ::class .java)
80+ account?.idToken?.let { firebaseAuthWithGoogle(it) }
81+ } catch (e: ApiException ) {
82+ Toast .makeText(this , getString(R .string.google_sign_in_failed, e.message), Toast .LENGTH_SHORT ).show()
83+ }
84+ }
85+
7486 private fun firebaseAuthWithGoogle (idToken : String ) {
7587 val credential = GoogleAuthProvider .getCredential(idToken, null )
7688 auth.signInWithCredential(credential)
77- .addOnCompleteListener(this ) { task ->
78- if (task.isSuccessful) {
79- val user = auth.currentUser
80- user?.email?.let { email ->
81- preferencesManager.isLoggedIn = true
82- preferencesManager.isGuestMode = false
83- preferencesManager.saveString(" pref_user_email" , email)
84- handleSuccessfulLogin()
85- }
86- } else {
87- Toast .makeText(this , " Authentication failed" , Toast .LENGTH_SHORT ).show()
89+ .addOnSuccessListener { authResult ->
90+ authResult.user?.email?.let { email ->
91+ handleSuccessfulAuth(email)
8892 }
8993 }
94+ .addOnFailureListener {
95+ Toast .makeText(this , getString(R .string.authentication_failed), Toast .LENGTH_SHORT ).show()
96+ }
9097 }
9198
9299 private fun setupViews () {
@@ -99,43 +106,53 @@ class LoginActivity : BaseActivity() {
99106
100107 private fun setupClickListeners () {
101108 binding.btnLogin.setOnClickListener {
102- val email = binding.etEmail.text.toString()
103- val password = binding.etPassword.text.toString()
104-
105- if (validateInputs(email, password)) {
106- checkIfEmailExists(email) { exists ->
107- if (exists) {
108- doSignin(email, password)
109- } else {
110- showSignUpConfirmation(email, password)
111- }
112- }
113- }
109+ handleLoginButtonClick()
114110 }
115111
116112 binding.btnGoogleSignIn.setSize(SignInButton .SIZE_WIDE )
117113 binding.btnGoogleSignIn.setOnClickListener {
118- val signInIntent = googleSignInClient.signInIntent
119- googleSignInLauncher.launch(signInIntent)
114+ signInWithGoogle()
120115 }
121116
122117 binding.btnContinueAsGuest.setOnClickListener {
123- preferencesManager.isGuestMode = true
124- navigateToMain()
118+ continueAsGuest()
125119 }
126120 }
127121
128- fun doSignin (email : String , password : String ){
129- auth.signInWithEmailAndPassword(email, password)
130- .addOnCompleteListener(this ) { task ->
131- if (task.isSuccessful) {
132- handleSuccessfulAuth(email)
122+ private fun handleLoginButtonClick () {
123+ val email = binding.etEmail.text.toString()
124+ val password = binding.etPassword.text.toString()
125+
126+ if (validateInputs(email, password)) {
127+ checkIfEmailExists(email) { exists ->
128+ if (exists) {
129+ doSignin(email, password)
133130 } else {
134- val exception = task.exception
135- Toast .makeText(this , " Authentication failed: ${exception?.message} " ,
136- Toast .LENGTH_LONG ).show()
131+ createNewAccount(email, password)
137132 }
138133 }
134+ }
135+ }
136+
137+ private fun signInWithGoogle () {
138+ val signInIntent = googleSignInClient.signInIntent
139+ googleSignInLauncher.launch(signInIntent)
140+ }
141+
142+ private fun continueAsGuest () {
143+ preferencesManager.isGuestMode = true
144+ navigateToMain()
145+ }
146+
147+ private fun doSignin (email : String , password : String ) {
148+ auth.signInWithEmailAndPassword(email, password)
149+ .addOnSuccessListener {
150+ checkAndSendEmailVerification(it.user)
151+ }
152+ .addOnFailureListener { exception ->
153+ Toast .makeText(this , getString(R .string.authentication_failed_with_message, exception.message),
154+ Toast .LENGTH_LONG ).show()
155+ }
139156 }
140157
141158 fun checkIfEmailExists (email : String , onResult : (Boolean ) -> Unit ) {
@@ -151,43 +168,96 @@ class LoginActivity : BaseActivity() {
151168 }
152169
153170 private fun showSignUpConfirmation (email : String , password : String ) {
154- android.app. AlertDialog .Builder (this )
155- .setTitle(" Create New Account " )
156- .setMessage(" Would you like to create a new account with this email? \n\n $email " )
157- .setPositiveButton(" Create Account " ) { _, _ ->
171+ AlertDialog .Builder (this )
172+ .setTitle(R .string.create_new_account )
173+ .setMessage(getString( R .string.create_new_account_prompt, email) )
174+ .setPositiveButton(R .string.create_account ) { _, _ ->
158175 createNewAccount(email, password)
159176 }
160- .setNegativeButton(" Cancel " , null )
177+ .setNegativeButton(android. R .string.cancel , null )
161178 .show()
162179 }
163180
164181 private fun createNewAccount (email : String , password : String ) {
165182 auth.createUserWithEmailAndPassword(email, password)
166- .addOnCompleteListener(this ) { task ->
167- if (task.isSuccessful) {
168- Toast .makeText(this , " Account created successfully!" , Toast .LENGTH_SHORT ).show()
169- handleSuccessfulAuth(email)
170- } else {
171- when {
172- task.exception?.message?.contains(" email address is already" , ignoreCase = true ) == true -> {
173- Toast .makeText(this , " This email is already registered. Please try signing in." , Toast .LENGTH_LONG ).show()
174- }
175- task.exception?.message?.contains(" credential is incorrect" , ignoreCase = true ) == true -> {
176- Toast .makeText(this , " Please use a valid email and a password with at least 6 characters" , Toast .LENGTH_LONG ).show()
177- }
178- else -> {
179- Toast .makeText(this , " Failed to create account: ${task.exception?.message} " ,
180- Toast .LENGTH_LONG ).show()
181- }
183+ .addOnSuccessListener {
184+ checkAndSendEmailVerification(it.user)
185+ }
186+ .addOnFailureListener { exception ->
187+ val message = when {
188+ exception.message?.contains(EMAIL_ALREADY_EXISTS , ignoreCase = true ) == true -> {
189+ doSignin(email, password)
190+ // getString(R.string.email_already_registered)
191+ " "
192+ }
193+ exception.message?.contains(INVALID_CREDENTIALS , ignoreCase = true ) == true -> {
194+ getString(R .string.invalid_email_or_password_length)
195+ }
196+ else -> {
197+ getString(R .string.create_account_failed, exception.message)
182198 }
183199 }
200+ if (message.isNotEmpty())
201+ Toast .makeText(this , message, Toast .LENGTH_LONG ).show()
184202 }
185203 }
186204
205+ private fun checkAndSendEmailVerification (user : FirebaseUser ? ) {
206+ if (user != null && ! user.isEmailVerified) {
207+ user.sendEmailVerification()
208+ .addOnSuccessListener {
209+ Toast .makeText(this , getString(R .string.verification_email_sent, user.email), Toast .LENGTH_SHORT ).show()
210+ showVerificationDialog(user)
211+ }
212+ .addOnFailureListener { exception ->
213+ Toast .makeText(this , getString(R .string.verification_email_failed, exception.message), Toast .LENGTH_SHORT ).show()
214+ }
215+ } else {
216+ user?.email?.let { handleSuccessfulAuth(it) }
217+ }
218+ }
219+
220+ private fun showVerificationDialog (user : FirebaseUser ) {
221+ val builder: AlertDialog .Builder = AlertDialog .Builder (this )
222+ builder.setTitle(getString(R .string.verify_your_email))
223+ builder.setMessage(getString(R .string.verification_dialog_message, user.email))
224+
225+ builder.setPositiveButton(getString(R .string.i_ve_verified)) { _, _ ->
226+ user.reload()
227+ .addOnSuccessListener {
228+ if (user.isEmailVerified) {
229+ Toast .makeText(this , getString(R .string.email_verified), Toast .LENGTH_SHORT ).show()
230+ user.email?.let { handleSuccessfulAuth(it) }
231+ } else {
232+ Toast .makeText(this , getString(R .string.email_not_verified_yet), Toast .LENGTH_SHORT ).show()
233+ showVerificationDialog(user)
234+ }
235+ }
236+ .addOnFailureListener { exception ->
237+ Toast .makeText(this , getString(R .string.verification_check_failed, exception.message), Toast .LENGTH_SHORT ).show()
238+ }
239+ }
240+
241+ builder.setNeutralButton(getString(R .string.resend_email)) { _, _ ->
242+ user.sendEmailVerification()
243+ .addOnSuccessListener {
244+ Toast .makeText(this , getString(R .string.verification_email_resent, user.email), Toast .LENGTH_SHORT ).show()
245+ }
246+ .addOnFailureListener { exception ->
247+ Toast .makeText(this , getString(R .string.failed_to_resend_email, exception.message), Toast .LENGTH_SHORT ).show()
248+ }
249+ }
250+
251+ builder.setNegativeButton(getString(R .string.contact_permission_dialog_cancel)) { dialog, _ -> dialog.dismiss() }
252+
253+ builder.setCancelable(false )
254+ builder.show()
255+ }
256+
187257 private fun handleSuccessfulAuth (email : String ) {
188258 preferencesManager.isLoggedIn = true
189259 preferencesManager.isGuestMode = false
190- preferencesManager.saveString(" pref_user_email " , email)
260+ preferencesManager.saveString(PREF_USER_EMAIL , email)
191261 handleSuccessfulLogin()
192262 }
193263
@@ -235,4 +305,4 @@ class LoginActivity : BaseActivity() {
235305 startActivity(Intent (this , MainActivity ::class .java))
236306 finish()
237307 }
238- }
308+ }
0 commit comments