@@ -2,21 +2,22 @@ package com.blurr.voice.utilities
22
33import android.util.Log
44import com.google.firebase.Firebase
5+ import com.google.firebase.Timestamp
56import com.google.firebase.auth.auth
67import com.google.firebase.firestore.FieldValue
78import com.google.firebase.firestore.firestore
89import com.revenuecat.purchases.Purchases
910import com.revenuecat.purchases.awaitCustomerInfo
10-
1111import kotlinx.coroutines.tasks.await
12+ import java.util.Calendar
1213
1314class FreemiumManager {
1415
1516 private val db = Firebase .firestore
1617 private val auth = Firebase .auth
1718
1819 companion object {
19- const val FREE_PLAN_TASK_LIMIT = 100 // Set your free task limit here
20+ const val DAILY_TASK_LIMIT = 100 // Set your daily task limit here
2021 }
2122
2223 private suspend fun isUserSubscribed (): Boolean {
@@ -29,28 +30,61 @@ class FreemiumManager {
2930 }
3031 }
3132
32- /* *
33- * Checks if a user document exists in Firestore. If not, creates one with
34- * the default free plan values. This should be called upon successful login.
35- */
33+ private fun isSameDay (timestamp : Timestamp ): Boolean {
34+ val calendar1 = Calendar .getInstance()
35+ calendar1.time = timestamp.toDate()
36+ val calendar2 = Calendar .getInstance() // Current time
37+
38+ return calendar1.get(Calendar .YEAR ) == calendar2.get(Calendar .YEAR ) &&
39+ calendar1.get(Calendar .DAY_OF_YEAR ) == calendar2.get(Calendar .DAY_OF_YEAR )
40+ }
41+
42+ private suspend fun resetDailyTasksIfNeeded (uid : String ) {
43+ val userDocRef = db.collection(" users" ).document(uid)
44+ try {
45+ db.runTransaction { transaction ->
46+ val snapshot = transaction.get(userDocRef)
47+ val lastReset = snapshot.getTimestamp(" tasksResetDate" )
48+
49+ if (lastReset == null || ! isSameDay(lastReset)) {
50+ Log .d(" FreemiumManager" , " New day detected. Resetting tasks for user $uid ." )
51+ transaction.update(userDocRef, " tasksRemaining" , DAILY_TASK_LIMIT )
52+ transaction.update(userDocRef, " tasksResetDate" , FieldValue .serverTimestamp())
53+ }
54+ }.await()
55+ } catch (e: Exception ) {
56+ Log .e(" FreemiumManager" , " Error in daily task reset transaction" , e)
57+ }
58+ }
59+
3660 suspend fun provisionUserIfNeeded () {
37- val currentUser = auth.currentUser ? : return // Should not be null if called after login
61+ val currentUser = auth.currentUser ? : return
3862 val userDocRef = db.collection(" users" ).document(currentUser.uid)
3963
4064 try {
4165 val document = userDocRef.get().await()
4266 if (! document.exists()) {
43- Log .d(" FreemiumManager" , " User document does not exist for UID ${currentUser.uid} . Provisioning new user. " )
67+ Log .d(" FreemiumManager" , " Provisioning new user: ${currentUser.uid} " )
4468 val newUser = hashMapOf(
4569 " email" to currentUser.email,
4670 " plan" to " free" ,
47- " tasksRemaining" to FREE_PLAN_TASK_LIMIT ,
48- " createdAt" to FieldValue .serverTimestamp()
71+ " tasksRemaining" to DAILY_TASK_LIMIT ,
72+ " createdAt" to FieldValue .serverTimestamp(),
73+ " tasksResetDate" to FieldValue .serverTimestamp() // Set initial reset date
4974 )
5075 userDocRef.set(newUser).await()
51- Log .d(" FreemiumManager" , " Successfully provisioned user." )
5276 } else {
53- Log .d(" FreemiumManager" , " User document already exists for UID ${currentUser.uid} ." )
77+ // For existing users, check if they need the new daily limit fields
78+ if (! document.contains(" tasksResetDate" )) {
79+ Log .d(" FreemiumManager" , " Migrating existing user ${currentUser.uid} to daily limit system." )
80+ userDocRef.update(mapOf (
81+ " tasksRemaining" to DAILY_TASK_LIMIT ,
82+ " tasksResetDate" to FieldValue .serverTimestamp()
83+ )).await()
84+ } else {
85+ // This is a good place to reset their tasks if it's a new day
86+ resetDailyTasksIfNeeded(currentUser.uid)
87+ }
5488 }
5589 } catch (e: Exception ) {
5690 Log .e(" FreemiumManager" , " Error provisioning user" , e)
@@ -60,56 +94,51 @@ class FreemiumManager {
6094 suspend fun getTasksRemaining (): Long? {
6195 if (isUserSubscribed()) return Long .MAX_VALUE
6296 val currentUser = auth.currentUser ? : return null
97+ resetDailyTasksIfNeeded(currentUser.uid) // Ensure tasks are up-to-date before fetching
6398 return try {
6499 val document = db.collection(" users" ).document(currentUser.uid).get().await()
65100 document.getLong(" tasksRemaining" )
66101 } catch (e: Exception ) {
67102 Log .e(" FreemiumManager" , " Error fetching tasks remaining" , e)
68- null // Return null on error so the UI can handle it
103+ null
69104 }
70105 }
71- /* *
72- * Checks if the user can perform a task.
73- * This is a simple read operation.
74- * @return true if tasksRemaining > 0, false otherwise.
75- */
106+
76107 suspend fun canPerformTask (): Boolean {
77108 if (isUserSubscribed()) return true
78-
79- val currentUser = auth.currentUser
80- if (currentUser == null ) {
81- Log .w(" FreemiumManager" , " Cannot check task count, user is not logged in." )
82- return false
83- }
109+ val currentUser = auth.currentUser ? : return false
110+ resetDailyTasksIfNeeded(currentUser.uid) // Crucial check before verifying task count
84111
85112 return try {
86113 val document = db.collection(" users" ).document(currentUser.uid).get().await()
87114 val tasksRemaining = document.getLong(" tasksRemaining" ) ? : 0
88- Log .d(" FreemiumManager" , " User has $tasksRemaining tasks remaining." )
115+ Log .d(" FreemiumManager" , " User has $tasksRemaining tasks remaining today ." )
89116 tasksRemaining > 0
90117 } catch (e: Exception ) {
91118 Log .e(" FreemiumManager" , " Error fetching user task count" , e)
92- false // Fail safely, preventing task execution on error
119+ false
93120 }
94121 }
95122
96- /* *
97- * Decrements the user's task count by 1.
98- * Uses an atomic increment operation for safety.
99- * This is a "fire and forget" call, we don't block the UI for it.
100- */
101123 suspend fun decrementTaskCount () {
102124 if (isUserSubscribed()) return
103-
104125 val currentUser = auth.currentUser ? : return
105- db.collection(" users" ).document(currentUser.uid)
106- .update(" tasksRemaining" , FieldValue .increment(- 1 ))
107- .addOnSuccessListener {
108- Log .d(" FreemiumManager" , " Successfully decremented task count for user ${currentUser.uid} ." )
109- }
110- .addOnFailureListener { e ->
111- Log .e(" FreemiumManager" , " Failed to decrement task count." , e)
112- // You might want to add logic here to retry or log this failure more robustly
113- }
126+
127+ val userDocRef = db.collection(" users" ).document(currentUser.uid)
128+ resetDailyTasksIfNeeded(currentUser.uid) // Ensure we don't decrement on a stale count
129+
130+ // Decrement only if tasks are remaining
131+ val tasksRemaining = getTasksRemaining()
132+ if (tasksRemaining != null && tasksRemaining > 0 ) {
133+ userDocRef.update(" tasksRemaining" , FieldValue .increment(- 1 ))
134+ .addOnSuccessListener {
135+ Log .d(" FreemiumManager" , " Successfully decremented task count for user ${currentUser.uid} ." )
136+ }
137+ .addOnFailureListener { e ->
138+ Log .e(" FreemiumManager" , " Failed to decrement task count." , e)
139+ }
140+ } else {
141+ Log .w(" FreemiumManager" , " Attempted to decrement task count, but none were left." )
142+ }
114143 }
115144}
0 commit comments