1+ package com.kharagedition.tibetankeyboard
2+
3+ import android.content.Intent
4+ import android.graphics.Color
5+ import android.net.Uri
6+ import android.os.Bundle
7+ import android.text.SpannableString
8+ import android.text.Spanned
9+ import android.text.TextPaint
10+ import android.text.method.LinkMovementMethod
11+ import android.text.style.ClickableSpan
12+ import android.view.View
13+ import android.widget.TextView
14+ import android.widget.Toast
15+ import androidx.activity.result.contract.ActivityResultContracts
16+ import androidx.appcompat.app.AppCompatActivity
17+ import androidx.core.content.ContextCompat
18+ import androidx.core.view.ViewCompat
19+ import androidx.core.view.WindowInsetsCompat
20+ import com.google.android.gms.auth.api.signin.GoogleSignIn
21+ import com.google.android.gms.auth.api.signin.GoogleSignInClient
22+ import com.google.android.gms.auth.api.signin.GoogleSignInOptions
23+ import com.google.android.gms.common.api.ApiException
24+ import com.google.android.material.button.MaterialButton
25+ import com.google.android.material.progressindicator.CircularProgressIndicator
26+ import com.google.firebase.auth.FirebaseAuth
27+ import com.google.firebase.auth.GoogleAuthProvider
28+ import com.google.firebase.auth.ktx.auth
29+ import com.google.firebase.ktx.Firebase
30+ import com.kharagedition.tibetankeyboard.R
31+ import com.kharagedition.tibetankeyboard.UserPreferences
32+ import com.kharagedition.tibetankeyboard.ui.ChatActivity
33+
34+ class LoginActivity : AppCompatActivity () {
35+
36+ private lateinit var auth: FirebaseAuth
37+ private lateinit var googleSignInClient: GoogleSignInClient
38+ private lateinit var buttonGoogleSignIn: MaterialButton
39+ private lateinit var progressIndicator: CircularProgressIndicator
40+ private lateinit var userPreferences: UserPreferences
41+ private lateinit var textViewPrivacyPolicy: TextView
42+
43+ private val googleSignInLauncher = registerForActivityResult(
44+ ActivityResultContracts .StartActivityForResult ()
45+ ) { result ->
46+ val task = GoogleSignIn .getSignedInAccountFromIntent(result.data)
47+ try {
48+ val account = task.getResult(ApiException ::class .java)!!
49+ firebaseAuthWithGoogle(account.idToken!! )
50+ } catch (e: ApiException ) {
51+ hideLoading()
52+ Toast .makeText(this , " Google sign in failed: ${e.message} " , Toast .LENGTH_SHORT ).show()
53+ }
54+ }
55+
56+ override fun onCreate (savedInstanceState : Bundle ? ) {
57+ super .onCreate(savedInstanceState)
58+ setContentView(R .layout.activity_login)
59+
60+ // Initialize Firebase Auth
61+ auth = Firebase .auth
62+ userPreferences = UserPreferences (this )
63+
64+ // Check if user is already signed in
65+ if (auth.currentUser != null && userPreferences.isUserLoggedIn()) {
66+ navigateToChatActivity()
67+ return
68+ }
69+
70+ // setupEdgeToEdge()
71+ initializeViews()
72+ setupPrivacyTextView()
73+ configureGoogleSignIn()
74+ setupClickListeners()
75+ }
76+
77+ private fun setupPrivacyTextView () {
78+ val fullText = " By signing in, you agree to our Terms of Service and Privacy Policy"
79+ val spannableString = SpannableString (fullText)
80+
81+ // Find the positions of the links
82+ val termsStart = fullText.indexOf(" Terms of Service" )
83+ val termsEnd = termsStart + " Terms of Service" .length
84+ val privacyStart = fullText.indexOf(" Privacy Policy" )
85+ val privacyEnd = privacyStart + " Privacy Policy" .length
86+ val termsClickableSpan = object : ClickableSpan () {
87+ override fun onClick (widget : View ) {
88+ openTermsOfService()
89+ }
90+
91+ override fun updateDrawState (ds : TextPaint ) {
92+ super .updateDrawState(ds)
93+ ds.color = ContextCompat .getColor(this @LoginActivity, R .color.brown_700)
94+ ds.isUnderlineText = true
95+ }
96+ }
97+
98+ val privacyClickableSpan = object : ClickableSpan () {
99+ override fun onClick (widget : View ) {
100+ openPrivacyPolicy()
101+ }
102+
103+ override fun updateDrawState (ds : TextPaint ) {
104+ super .updateDrawState(ds)
105+ ds.color = ContextCompat .getColor(this @LoginActivity, R .color.brown_700)
106+ ds.isUnderlineText = true
107+ }
108+ }
109+
110+ // Apply the spans
111+ spannableString.setSpan(termsClickableSpan, termsStart, termsEnd, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE )
112+ spannableString.setSpan(privacyClickableSpan, privacyStart, privacyEnd, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE )
113+
114+ // Set the text and make it clickable
115+ textViewPrivacyPolicy.text = spannableString
116+ textViewPrivacyPolicy.movementMethod = LinkMovementMethod .getInstance()
117+
118+ // Optional: Remove the default link color highlighting
119+ textViewPrivacyPolicy.highlightColor = Color .TRANSPARENT
120+
121+
122+ }
123+ private fun openTermsOfService () {
124+ val intent = Intent (Intent .ACTION_VIEW , Uri .parse(" https://kharagedition.github.io/term-and-condition/tibetan-keyboard.html" ))
125+ startActivity(intent)
126+ }
127+
128+ private fun openPrivacyPolicy () {
129+ val intent = Intent (Intent .ACTION_VIEW , Uri .parse(" https://kharagedition.github.io/privacy-policy/tibetan-keyboard" ))
130+ startActivity(intent)
131+ }
132+
133+ private fun setupEdgeToEdge () {
134+ ViewCompat .setOnApplyWindowInsetsListener(findViewById(R .id.main_container)) { v, insets ->
135+ val systemBars = insets.getInsets(WindowInsetsCompat .Type .systemBars())
136+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
137+ insets
138+ }
139+ }
140+
141+ private fun initializeViews () {
142+ buttonGoogleSignIn = findViewById(R .id.buttonGoogleSignIn)
143+ progressIndicator = findViewById(R .id.progressIndicator)
144+ textViewPrivacyPolicy = findViewById(R .id.textViewPrivacy)
145+ }
146+
147+ private fun configureGoogleSignIn () {
148+ val gso = GoogleSignInOptions .Builder (GoogleSignInOptions .DEFAULT_SIGN_IN )
149+ .requestIdToken(getString(R .string.default_web_client_id))
150+ .requestEmail()
151+ .requestProfile()
152+ .build()
153+
154+ googleSignInClient = GoogleSignIn .getClient(this , gso)
155+ }
156+
157+ private fun setupClickListeners () {
158+ buttonGoogleSignIn.setOnClickListener {
159+ signInWithGoogle()
160+ }
161+ }
162+
163+ private fun signInWithGoogle () {
164+ showLoading()
165+ val signInIntent = googleSignInClient.signInIntent
166+ googleSignInLauncher.launch(signInIntent)
167+ }
168+
169+ private fun firebaseAuthWithGoogle (idToken : String ) {
170+ val credential = GoogleAuthProvider .getCredential(idToken, null )
171+ auth.signInWithCredential(credential)
172+ .addOnCompleteListener(this ) { task ->
173+ hideLoading()
174+ if (task.isSuccessful) {
175+ val user = auth.currentUser
176+ user?.let {
177+ // Save user login state
178+ userPreferences.saveUserLoginState(
179+ isLoggedIn = true ,
180+ userId = it.uid,
181+ userName = it.displayName ? : " User" ,
182+ userEmail = it.email ? : " " ,
183+ userPhotoUrl = it.photoUrl?.toString() ? : " "
184+ )
185+
186+ Toast .makeText(this , " Welcome ${it.displayName} !" , Toast .LENGTH_SHORT ).show()
187+ navigateToChatActivity()
188+ }
189+ } else {
190+ Toast .makeText(
191+ this ,
192+ " Authentication failed: ${task.exception?.message} " ,
193+ Toast .LENGTH_SHORT
194+ ).show()
195+ }
196+ }
197+ }
198+
199+ private fun showLoading () {
200+ buttonGoogleSignIn.text = " "
201+ buttonGoogleSignIn.isEnabled = false
202+ progressIndicator.visibility = android.view.View .VISIBLE
203+ }
204+
205+ private fun hideLoading () {
206+ buttonGoogleSignIn.text = getString(R .string.sign_in_with_google)
207+ buttonGoogleSignIn.isEnabled = true
208+ progressIndicator.visibility = android.view.View .GONE
209+ }
210+
211+ private fun navigateToChatActivity () {
212+ val intent = Intent (this , ChatActivity ::class .java)
213+ // intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
214+ startActivity(intent)
215+ finish()
216+ }
217+
218+ public override fun onStart () {
219+ super .onStart()
220+ // Check if user is signed in and update UI accordingly
221+ val currentUser = auth.currentUser
222+ if (currentUser != null && userPreferences.isUserLoggedIn()) {
223+ navigateToChatActivity()
224+ }
225+ }
226+ }
0 commit comments