Skip to content

Commit e8a8361

Browse files
added firestore
1 parent 78b3428 commit e8a8361

5 files changed

Lines changed: 385 additions & 22 deletions

File tree

app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
applicationId "com.kharagedition.tibetankeyboard"
1313
minSdkVersion 23
1414
targetSdkVersion 35
15-
versionCode 12
16-
versionName "1.3.13"
15+
versionCode 13
16+
versionName "1.4.14"
1717

1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1919
multiDexEnabled true
@@ -64,6 +64,7 @@ dependencies {
6464
implementation platform('com.google.firebase:firebase-bom:33.9.0')
6565
implementation 'com.google.firebase:firebase-crashlytics-ktx'
6666
implementation 'com.google.firebase:firebase-auth-ktx'
67+
implementation 'com.google.firebase:firebase-firestore-ktx'
6768
implementation 'com.google.android.gms:play-services-auth:20.7.0'
6869
implementation 'com.airbnb.android:lottie:6.2.0'
6970
implementation 'com.github.bumptech.glide:glide:4.16.0'

app/src/main/java/com/kharagedition/tibetankeyboard/LoginActivity.kt

Lines changed: 98 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@ import androidx.appcompat.app.AppCompatActivity
1717
import androidx.core.content.ContextCompat
1818
import androidx.core.view.ViewCompat
1919
import androidx.core.view.WindowInsetsCompat
20+
import androidx.lifecycle.lifecycleScope
2021
import com.google.android.gms.auth.api.signin.GoogleSignIn
2122
import com.google.android.gms.auth.api.signin.GoogleSignInClient
2223
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
2324
import com.google.android.gms.common.api.ApiException
2425
import com.google.android.material.button.MaterialButton
2526
import com.google.android.material.progressindicator.CircularProgressIndicator
27+
import com.google.firebase.FirebaseNetworkException
2628
import com.google.firebase.auth.FirebaseAuth
29+
import com.google.firebase.auth.FirebaseAuthUserCollisionException
30+
import com.google.firebase.auth.FirebaseUser
2731
import com.google.firebase.auth.GoogleAuthProvider
2832
import com.google.firebase.auth.ktx.auth
2933
import com.google.firebase.ktx.Firebase
3034
import com.kharagedition.tibetankeyboard.R
3135
import com.kharagedition.tibetankeyboard.UserPreferences
36+
import com.kharagedition.tibetankeyboard.repo.UserRepository
3237
import com.kharagedition.tibetankeyboard.ui.ChatActivity
38+
import kotlinx.coroutines.launch
3339

3440
class LoginActivity : AppCompatActivity() {
3541

@@ -39,6 +45,7 @@ class LoginActivity : AppCompatActivity() {
3945
private lateinit var progressIndicator: CircularProgressIndicator
4046
private lateinit var userPreferences: UserPreferences
4147
private lateinit var textViewPrivacyPolicy: TextView
48+
private lateinit var userRepository: UserRepository
4249

4350
private val googleSignInLauncher = registerForActivityResult(
4451
ActivityResultContracts.StartActivityForResult()
@@ -59,6 +66,7 @@ class LoginActivity : AppCompatActivity() {
5966

6067
// Initialize Firebase Auth
6168
auth = Firebase.auth
69+
userRepository = UserRepository()
6270
userPreferences = UserPreferences(this)
6371

6472
// Check if user is already signed in
@@ -173,27 +181,104 @@ class LoginActivity : AppCompatActivity() {
173181
hideLoading()
174182
if (task.isSuccessful) {
175183
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-
)
184+
user?.let { firebaseUser ->
185+
handleSuccessfulLogin(firebaseUser, task.result?.additionalUserInfo?.isNewUser ?: false)
186+
}
187+
} else {
188+
handleLoginError(task.exception)
189+
}
190+
}
191+
}
192+
193+
private fun handleSuccessfulLogin(firebaseUser: FirebaseUser, isNewUser: Boolean) {
194+
// Save user login state locally
195+
userPreferences.saveUserLoginState(
196+
isLoggedIn = true,
197+
userId = firebaseUser.uid,
198+
userName = firebaseUser.displayName ?: "User",
199+
userEmail = firebaseUser.email ?: "",
200+
userPhotoUrl = firebaseUser.photoUrl?.toString() ?: ""
201+
)
202+
203+
// Create or update user in Firestore
204+
lifecycleScope.launch {
205+
try {
206+
showLoading()
207+
208+
val result = userRepository.createOrUpdateUser(
209+
uid = firebaseUser.uid,
210+
displayName = firebaseUser.displayName ?: "User",
211+
email = firebaseUser.email ?: "",
212+
photoUrl = firebaseUser.photoUrl?.toString() ?: "",
213+
context = this@LoginActivity,
214+
isNewUser = isNewUser
215+
)
216+
217+
hideLoading()
185218

186-
Toast.makeText(this, "Welcome ${it.displayName}!", Toast.LENGTH_SHORT).show()
187-
navigateToChatActivity()
219+
if (result.isSuccess) {
220+
val user = result.getOrNull()
221+
val welcomeMessage = if (isNewUser) {
222+
"Welcome to our app, ${firebaseUser.displayName}!"
223+
} else {
224+
"Welcome back, ${firebaseUser.displayName}!"
188225
}
226+
227+
Toast.makeText(this@LoginActivity, welcomeMessage, Toast.LENGTH_SHORT).show()
228+
229+
// Track successful login
230+
userRepository.trackUserEvent(
231+
firebaseUser.uid,
232+
if (isNewUser) "user_registration_completed" else "user_login_success",
233+
mapOf(
234+
"login_method" to "google",
235+
"user_email" to (firebaseUser.email ?: ""),
236+
"has_display_name" to (firebaseUser.displayName != null)
237+
)
238+
)
239+
240+
navigateToChatActivity()
189241
} else {
242+
// Even if Firestore fails, continue with login but show warning
190243
Toast.makeText(
191-
this,
192-
"Authentication failed: ${task.exception?.message}",
244+
this@LoginActivity,
245+
"Welcome ${firebaseUser.displayName}! (Profile sync pending)",
193246
Toast.LENGTH_SHORT
194247
).show()
248+
navigateToChatActivity()
195249
}
250+
} catch (e: Exception) {
251+
hideLoading()
252+
// Don't block login for data collection failures
253+
Toast.makeText(
254+
this@LoginActivity,
255+
"Welcome ${firebaseUser.displayName}!",
256+
Toast.LENGTH_SHORT
257+
).show()
258+
navigateToChatActivity()
196259
}
260+
}
261+
}
262+
private fun handleLoginError(exception: Exception?) {
263+
val errorMessage = when (exception) {
264+
is FirebaseAuthUserCollisionException -> "An account already exists with this email"
265+
is FirebaseNetworkException -> "Network error. Please check your connection"
266+
else -> "Authentication failed: ${exception?.message}"
267+
}
268+
269+
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show()
270+
271+
// Track failed login attempt
272+
lifecycleScope.launch {
273+
userRepository.trackUserEvent(
274+
"anonymous",
275+
"login_failed",
276+
mapOf(
277+
"error_message" to (exception?.message ?: "Unknown error"),
278+
"login_method" to "google"
279+
)
280+
)
281+
}
197282
}
198283

199284
private fun showLoading() {

app/src/main/java/com/kharagedition/tibetankeyboard/UserPreferences.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ class UserPreferences(context: Context) {
99
context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
1010

1111
companion object {
12-
private const val PREF_NAME = "user_preferences"
13-
private const val KEY_IS_LOGGED_IN = "is_logged_in"
14-
private const val KEY_USER_ID = "user_id"
15-
private const val KEY_USER_NAME = "user_name"
16-
private const val KEY_USER_EMAIL = "user_email"
17-
private const val KEY_USER_PHOTO_URL = "user_photo_url"
18-
private const val KEY_FIRST_TIME_USER = "first_time_user"
12+
private const val PREF_NAME = "userPreferences"
13+
private const val KEY_IS_LOGGED_IN = "isLoggedIn"
14+
private const val KEY_USER_ID = "userId"
15+
private const val KEY_USER_NAME = "username"
16+
private const val KEY_USER_EMAIL = "userEmail"
17+
private const val KEY_USER_PHOTO_URL = "userPhotoUrl"
18+
private const val KEY_FIRST_TIME_USER = "firstTimeUser"
1919
}
2020

2121
fun saveUserLoginState(

0 commit comments

Comments
 (0)