Skip to content

Instantly share code, notes, and snippets.

@eddieberklee
Created April 1, 2022 08:57
Show Gist options
  • Save eddieberklee/7474ac22426274b314e40d0cdb401b69 to your computer and use it in GitHub Desktop.
Save eddieberklee/7474ac22426274b314e40d0cdb401b69 to your computer and use it in GitHub Desktop.
HabitDay Firestore Model
class HabitDayFS {
lateinit var id: String
lateinit var habitId: String
@get:PropertyName("isCompleted")
@set:PropertyName("isCompleted")
var isCompleted: Boolean = false
var noteText: String = ""
lateinit var yearMonthDay: String
constructor() {}
constructor(habitId: String, ymd: YearMonthDay, isCompleted: Boolean) {
this.habitId = habitId
this.yearMonthDay = ymd
this.id = getKey(habitId, ymd)
this.isCompleted = isCompleted
}
fun deleteOnFirebase() {
getHabitDayReference(habitId, id)
.delete()
.addOnCompleteListener {
if (FirebaseEtil.handleFirestoreErrorTaskVoid(
it,
"Could not successfully delete the habit day")
) {
return@addOnCompleteListener
}
Timber.d("Successfully deleted habitId: $habitId")
}
}
fun updateFirestore() {
getCollectionReference()
.document(id)
.set(this)
.addOnCompleteListener {
if (FirebaseEtil.handleFirestoreErrorTaskVoid(it, "Failed to update habit day $id")) {
return@addOnCompleteListener
}
Timber.d("Successfully updated habit day $id")
}
}
companion object {
const val HABIT_DAY_COLLECTION = "habitDay"
const val FIELD_ID = "id" // year month day
const val FIELD_IS_COMPLETED = "isCompleted"
const val FIELD_NOTE_TEXT = "noteText"
const val FIELD_HABIT_ID = "habitId"
fun getCollectionReference(): CollectionReference {
return FirebaseFirestore
.getInstance()
.collection(HABIT_DAY_COLLECTION)
}
private fun getKey(habitId: String, ymd: YearMonthDay): String {
return "${AuthUtil.getUUID()}_${habitId}_$ymd"
}
fun fetchHabitDayOnce(
habitDayId: String,
onFetchCallback: ((habitDay: HabitDayFS) -> Unit)? = null
) {
getCollectionReference()
.document(habitDayId)
.get()
.addOnCompleteListener {
if (FirebaseEtil.handleFirestoreErrorDocumentSnapshot(
it,
"Failed to fetch habit day $habitDayId")
) {
return@addOnCompleteListener
}
Timber.d("Successfully fetched habit day $habitDayId")
val habitDay = it.result.toObject(HabitDayFS::class.java)!!
onFetchCallback?.invoke(habitDay)
}
}
@JvmStatic
@Exclude
fun updateIsCompletedInFirestore(
userEmail: String,
habitId: String,
ymd: String,
isCompleted: Boolean
) {
getHabitDayReference(habitId, ymd)
.update(FIELD_IS_COMPLETED, isCompleted)
.addOnSuccessListener { aVoid: Void? ->
Timber.d(
"Updated habitId: %s habitDayId: %s isCompleted: %s ymd $ymd",
habitId,
ymd,
isCompleted
)
}
.addOnFailureListener { e: Exception ->
Timber.e(
"Failed to update habit as completed userEmail: $userEmail yearMonthDay: $ymd habitId: $habitId")
CrashUtil.logAndShowToast(
"Failed to update habit as completed: ${e.message}"
)
}
}
@JvmStatic
@Exclude
fun getHabitDayReference(
habitId: String,
ymd: YearMonthDay
): DocumentReference {
return getCollectionReference()
.document(getKey(habitId, ymd))
}
@JvmStatic
@Exclude
fun createNewAsCompletedFirestore(
habitId: String,
ymd: String
) {
val newHabitDay = HabitDayFS(habitId, ymd, isCompleted = true)
getCollectionReference()
.document(getKey(habitId, ymd))
.set(newHabitDay)
.addOnCompleteListener {
if (FirebaseEtil.handleFirestoreErrorTaskVoid(
it,
"Failed to create new habit day ymd=$ymd id=${newHabitDay.id} habitId=$habitId")) {
return@addOnCompleteListener
}
Timber.d("Successfully created new habit day ymd=$ymd id=${newHabitDay.id} habitId=$habitId")
}
}
@JvmStatic
fun migrateData(uuid: String, email: String, onCompleteRunnable: Runnable) {
// querying each habit for its id
HabitFS.habitCollection
.get()
.addOnCompleteListener { task1: Task<QuerySnapshot> ->
if (CrashUtil.didHandleFirestoreException(task1.exception)) {
return@addOnCompleteListener
}
if (task1.isSuccessful) {
for (document in task1.result) {
val habit = document.toObject(HabitFS::class.java)
// todo: using habit id to get all habit days
getCollectionReference()
.get()
.addOnCompleteListener { task2: Task<QuerySnapshot> ->
if (CrashUtil.didHandleFirestoreException(task2.exception)) {
return@addOnCompleteListener
}
if (task2.isSuccessful) {
for (document1 in task2.result) {
val habitDay = document1.toObject(HabitDayFS::class.java)
// copying over all habit days
// todo: doesn't habit id need to b e used
getCollectionReference()
.add(habitDay)
.addOnCompleteListener { task3: Task<DocumentReference?> ->
if (CrashUtil.didHandleFirestoreException(task3.exception)) {
return@addOnCompleteListener
}
if (task3.isSuccessful) {
Timber.d(
"Successfully copied over habit day %s from %s to %s",
habitDay.id,
uuid,
email
)
onCompleteRunnable.run()
}
}
}
}
}
}
}
}
}
fun deleteAllHabitDays(habitId: String) {
getCollectionReference()
.get()
.addOnCompleteListener {
if (it.exception != null) {
CrashEtil.logAndShowToast(it.exception?.message)
return@addOnCompleteListener
}
for (documentSnapshot in it.result.documents) {
val habitDay = documentSnapshot.toObject(HabitDayFS::class.java)
// todo: is there a better way to delete documents from a collection?
habitDay?.deleteOnFirebase()
}
}
}
fun queryContinuously(
habitId: String,
callback: (List<HabitDayFS>) -> Unit
): ListenerRegistration {
return getCollectionReference()
.whereEqualTo(FIELD_HABIT_ID, habitId)
.addSnapshotListener { value, error ->
if (error != null) {
Timber.e("Failed to query habit days with habit id $habitId, message=${error.message}")
return@addSnapshotListener
}
Timber.d("Successful snapshot of new habit days (${value?.size()})")
val habitDays = value?.toObjects(HabitDayFS::class.java)
if (habitDays == null) {
Timber.d("Habit days is null")
} else {
callback.invoke(habitDays)
}
}
}
fun updateFieldsFirestore(habitDayId: String, updateMap: Map<String, Any>) {
getCollectionReference()
.document(habitDayId)
.update(updateMap)
.addOnCompleteListener {
if (FirebaseEtil.handleFirestoreErrorTaskVoid(
it,
"Failed to update fields for habit day id $habitDayId")) {
return@addOnCompleteListener
}
Timber.d("Successfully updated fields for habit day id $habitDayId")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment