calendario

This commit is contained in:
MeuNome
2026-05-12 17:16:45 +01:00
parent 2aa02bd434
commit 03074a881e
7 changed files with 169 additions and 82 deletions

View File

@@ -1230,6 +1230,18 @@
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="36" />
<option name="brand" value="samsung" />
<option name="codename" value="m1q" />
<option name="id" value="m1q" />
<option name="labId" value="google" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S26" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />

View File

@@ -1,6 +1,7 @@
package com.fluxup.app; package com.fluxup.app;
public class DailyProgress { public class DailyProgress {
public String userId;
public String date; public String date;
public int completedTasks; public int completedTasks;
public int dailyGoal; public int dailyGoal;
@@ -8,6 +9,9 @@ public class DailyProgress {
public int xp; public int xp;
public String status; // "complete", "partial", "empty" public String status; // "complete", "partial", "empty"
public boolean isGoalReached; public boolean isGoalReached;
public boolean isCompleted;
public Object createdAt;
public Object updatedAt;
public DailyProgress() {} public DailyProgress() {}
@@ -19,11 +23,14 @@ public class DailyProgress {
this.xp = 0; this.xp = 0;
this.status = "empty"; this.status = "empty";
this.isGoalReached = false; this.isGoalReached = false;
this.isCompleted = false;
} }
public void updateStatus() { public void updateStatus() {
if (isGoalReached || (completedTasks >= dailyGoal && dailyGoal > 0)) { if (isCompleted || isGoalReached || (completedTasks >= dailyGoal && dailyGoal > 0)) {
status = "complete"; status = "complete";
isCompleted = true;
isGoalReached = true;
} else if (completedTasks > 0) { } else if (completedTasks > 0) {
status = "partial"; status = "partial";
} else { } else {

View File

@@ -3,11 +3,14 @@ package com.fluxup.app;
import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.ListenerRegistration; import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.QueryDocumentSnapshot; import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.SetOptions;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.google.firebase.firestore.FieldValue;
import com.google.firebase.firestore.Query;
public class FirestoreManager { public class FirestoreManager {
@@ -369,4 +372,71 @@ public class FirestoreManager {
updateUserStats(uid, updates, () -> callback.accept(finalStreak)); updateUserStats(uid, updates, () -> callback.accept(finalStreak));
}); });
} }
/**
* Guarda ou atualiza o progresso diário na coleção daily_progress.
*/
public void saveDailyProgress(DailyProgress dp) {
if (dp.userId == null || dp.date == null) return;
String docId = dp.userId + "_" + dp.date;
android.util.Log.d("FLUXUP_DEBUG", "SAVE_DAILY_PROGRESS_START");
android.util.Log.d("FLUXUP_DEBUG", "USER_ID: " + dp.userId);
android.util.Log.d("FLUXUP_DEBUG", "TODAY_DATE: " + dp.date);
android.util.Log.d("FLUXUP_DEBUG", "COMPLETED_TASKS_TODAY: " + dp.completedTasks);
android.util.Log.d("FLUXUP_DEBUG", "DAILY_GOAL: " + dp.dailyGoal);
Map<String, Object> data = new java.util.HashMap<>();
data.put("userId", dp.userId);
data.put("date", dp.date);
data.put("completedTasks", dp.completedTasks);
data.put("dailyGoal", dp.dailyGoal);
data.put("focusSessions", dp.focusSessions);
data.put("xp", dp.xp);
data.put("isCompleted", dp.isCompleted);
data.put("updatedAt", FieldValue.serverTimestamp());
// Se for a primeira vez, definimos o createdAt
db.collection("daily_progress").document(docId).get().addOnSuccessListener(snapshot -> {
if (!snapshot.exists()) {
data.put("createdAt", FieldValue.serverTimestamp());
}
db.collection("daily_progress").document(docId).set(data, SetOptions.merge())
.addOnSuccessListener(aVoid -> android.util.Log.d("FLUXUP_DEBUG", "DAILY_PROGRESS_SAVED"))
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "DAILY_PROGRESS_SAVE_FAIL: " + e.getMessage()));
});
}
/**
* Procura o progresso diário de um utilizador num intervalo de datas.
*/
public void getMonthlyDailyProgress(String userId, String startDate, String endDate, Consumer<List<DailyProgress>> callback) {
android.util.Log.d("FLUXUP_DEBUG", "LOAD_MONTHLY_PROGRESS_START");
android.util.Log.d("FLUXUP_DEBUG", "MONTH_START: " + startDate);
android.util.Log.d("FLUXUP_DEBUG", "MONTH_END: " + endDate);
db.collection("daily_progress")
.whereEqualTo("userId", userId)
.whereEqualTo("isCompleted", true)
.whereGreaterThanOrEqualTo("date", startDate)
.whereLessThanOrEqualTo("date", endDate)
.get()
.addOnSuccessListener(snapshots -> {
List<DailyProgress> results = new ArrayList<>();
if (snapshots != null) {
for (QueryDocumentSnapshot doc : snapshots) {
DailyProgress dp = doc.toObject(DailyProgress.class);
results.add(dp);
}
}
android.util.Log.d("FLUXUP_DEBUG", "COMPLETED_DAYS_FROM_FIREBASE: " + results.size());
android.util.Log.d("FLUXUP_DEBUG", "DIAS_CUMPRIDOS_COUNT: " + results.size());
callback.accept(results);
})
.addOnFailureListener(e -> {
android.util.Log.e("FLUXUP_DEBUG", "LOAD_MONTHLY_PROGRESS_FAIL: " + e.getMessage());
callback.accept(new ArrayList<>());
});
}
} }

View File

@@ -396,7 +396,24 @@ public class InicioFragment extends Fragment {
int currentStreak = user.streak; int currentStreak = user.streak;
String lastStreakDate = user.last_streak_completed_date; String lastStreakDate = user.last_streak_completed_date;
boolean willIncrement = (completedTasksToday >= dailyTaskGoal) && !today.equals(lastStreakDate); boolean isGoalReached = (completedTasksToday >= dailyTaskGoal);
// PERSISTÊNCIA NO FIRESTORE (daily_progress)
DailyProgress dp = new DailyProgress(today, dailyTaskGoal);
dp.userId = user.id_usuario;
dp.completedTasks = completedTasksToday;
dp.isCompleted = isGoalReached;
dp.updateStatus();
FirestoreManager.getInstance().saveDailyProgress(dp);
// PERSISTÊNCIA DO HISTÓRICO REAL NO OBJETO USUÁRIO (Retrocompatibilidade)
if (isGoalReached && (user.dias_concluidos == null || !user.dias_concluidos.contains(today))) {
if (user.dias_concluidos == null) user.dias_concluidos = new java.util.ArrayList<>();
user.dias_concluidos.add(today);
FirestoreManager.getInstance().updateUserField(user.id_usuario, "dias_concluidos", com.google.firebase.firestore.FieldValue.arrayUnion(today));
}
boolean willIncrement = isGoalReached && !today.equals(lastStreakDate);
int displayedStreak = 0; int displayedStreak = 0;
if (completedTasksToday < dailyTaskGoal) { if (completedTasksToday < dailyTaskGoal) {
@@ -415,7 +432,7 @@ public class InicioFragment extends Fragment {
} }
FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates); FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates);
// NOVO: Adicionar log de conclusão permanente da meta // Adicionar log de conclusão permanente da meta
FirestoreManager.getInstance().addXpLog(user.id_usuario, 0, "daily_goal_reached"); FirestoreManager.getInstance().addXpLog(user.id_usuario, 0, "daily_goal_reached");
// Atualizar objeto local // Atualizar objeto local
@@ -621,35 +638,23 @@ public class InicioFragment extends Fragment {
ProgressBar nodeProgress = node.findViewById(R.id.nodeProgress); ProgressBar nodeProgress = node.findViewById(R.id.nodeProgress);
View rightConnector = node.findViewById(R.id.rightConnector); View rightConnector = node.findViewById(R.id.rightConnector);
// LÓGICA DE STATUS SOLICITADA // LÓGICA DE HISTÓRICO PERSISTENTE SOLICITADA
boolean isToday = (i == currentDayIndex); boolean isToday = (i == currentDayIndex);
int completedTasksFromLogs = (dp != null) ? dp.completedTasks : 0; boolean isDateCompleted = (user != null && user.dias_concluidos != null && user.dias_concluidos.contains(dateStr));
// Se for hoje, usamos o valor mais atualizado do objeto user
int completedTasksForDay = isToday ? Math.max(completedTasksFromLogs, (user != null ? user.tasks_concluidas_hoje : 0)) : completedTasksFromLogs;
int dailyTaskGoal = (dp != null && dp.dailyGoal > 0) ? dp.dailyGoal : 4;
if (dailyTaskGoal <= 0) dailyTaskGoal = 4;
// LÓGICA DE STATUS SOLICITADA
String status = "empty"; String status = "empty";
if (dp != null) dp.updateStatus(); if (isDateCompleted) {
if (dp != null && "complete".equals(dp.status)) {
status = "completed";
} else if (completedTasksForDay >= dailyTaskGoal) {
status = "completed"; status = "completed";
} else if (isToday) { } else if (isToday) {
status = "today"; status = "today";
} }
int completedTasksForDay = isToday ? (user != null ? user.tasks_concluidas_hoje : 0) : ((progressMap != null && progressMap.get(dateStr) != null) ? progressMap.get(dateStr).completedTasks : 0);
int dailyTaskGoal = (progressMap != null && progressMap.get(dateStr) != null && progressMap.get(dateStr).dailyGoal > 0) ? progressMap.get(dateStr).dailyGoal : (user != null ? user.meta_diaria_tarefas : 4);
if (dailyTaskGoal <= 0) dailyTaskGoal = 4;
// DEBUG LOGS // DEBUG LOGS
android.util.Log.d("FLUXUP_DEBUG", "WEEK_DAY: " + i); android.util.Log.d("FLUXUP_DEBUG", "WEEK_DAY: " + i + " | DATE: " + dateStr + " | COMPLETED: " + isDateCompleted + " | STATUS: " + status);
android.util.Log.d("FLUXUP_DEBUG", "DATE: " + dateStr);
android.util.Log.d("FLUXUP_DEBUG", "COMPLETED_TASKS: " + completedTasksForDay);
android.util.Log.d("FLUXUP_DEBUG", "DAILY_GOAL: " + dailyTaskGoal);
android.util.Log.d("FLUXUP_DEBUG", "IS_TODAY: " + isToday);
android.util.Log.d("FLUXUP_DEBUG", "FINAL_STATUS: " + status);
// RENDERIZAÇÃO // RENDERIZAÇÃO
if ("completed".equals(status)) { if ("completed".equals(status)) {
@@ -660,10 +665,9 @@ public class InicioFragment extends Fragment {
Calendar nextDayCal = (Calendar) dayCal.clone(); Calendar nextDayCal = (Calendar) dayCal.clone();
nextDayCal.add(Calendar.DAY_OF_YEAR, 1); nextDayCal.add(Calendar.DAY_OF_YEAR, 1);
String nextDateStr = sdf.format(nextDayCal.getTime()); String nextDateStr = sdf.format(nextDayCal.getTime());
DailyProgress nextDp = progressMap.get(nextDateStr); boolean isNextCompleted = (user != null && user.dias_concluidos != null && user.dias_concluidos.contains(nextDateStr));
// Se o próximo dia também estiver completo, conector verde if (isNextCompleted) {
if (nextDp != null && nextDp.completedTasks >= nextDp.dailyGoal && nextDp.dailyGoal > 0) {
rightConnector.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.success_green)); rightConnector.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.success_green));
} else { } else {
rightConnector.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.border_color)); rightConnector.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.border_color));

View File

@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class StreakActivity extends AppCompatActivity { public class StreakActivity extends AppCompatActivity {
@@ -116,74 +117,72 @@ public class StreakActivity extends AppCompatActivity {
endCal.add(Calendar.MONTH, 1); endCal.add(Calendar.MONTH, 1);
java.util.Date endDate = endCal.getTime(); java.util.Date endDate = endCal.getTime();
android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_LOAD_MONTH_START"); android.util.Log.d("FLUXUP_DEBUG", "STREAK_VALUE_FROM_HOME_SOURCE: " + (currentUserObj != null ? currentUserObj.streak : "null"));
android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_USER_ID: " + currentUserId); android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_USER_ID: " + currentUserId);
android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_MONTH_START: " + startDate); android.util.Log.d("FLUXUP_DEBUG", "LOAD_MONTHLY_PROGRESS_START");
android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_MONTH_END: " + endDate);
android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_CURRENT_DAILY_GOAL: " + currentDailyGoal);
FirestoreManager.getInstance().getDailyProgress(currentUserId, startDate, endDate, currentDailyGoal, progressMap -> { String startDateStr = String.format(Locale.US, "%04d-%02d-%02d", year, month + 1, 1);
Calendar endMonthCal = (Calendar) startCal.clone();
endMonthCal.set(Calendar.DAY_OF_MONTH, endMonthCal.getActualMaximum(Calendar.DAY_OF_MONTH));
String endDateStr = String.format(Locale.US, "%04d-%02d-%02d", year, month + 1, endMonthCal.getActualMaximum(Calendar.DAY_OF_MONTH));
android.util.Log.d("FLUXUP_DEBUG", "MONTH_START: " + startDateStr);
android.util.Log.d("FLUXUP_DEBUG", "MONTH_END: " + endDateStr);
FirestoreManager.getInstance().getMonthlyDailyProgress(currentUserId, startDateStr, endDateStr, progressList -> {
if (isDestroyed()) return; if (isDestroyed()) return;
android.util.Log.d("FLUXUP_DEBUG", "OFFENSIVA_PROGRESS_DATA_SIZE: " + progressMap.size()); android.util.Log.d("FLUXUP_DEBUG", "COMPLETED_DAYS_FROM_FIREBASE: " + progressList.size());
int focusSessionsCount = 0; int focusSessionsCount = 0;
Map<Integer, DailyProgress> dailyProgressMap = new HashMap<>(); Map<Integer, DailyProgress> dailyProgressMap = new HashMap<>();
Set<String> completedDatesThisMonth = new java.util.HashSet<>();
for (Map.Entry<String, DailyProgress> entry : progressMap.entrySet()) { for (DailyProgress dp : progressList) {
DailyProgress dp = entry.getValue();
focusSessionsCount += dp.focusSessions; focusSessionsCount += dp.focusSessions;
android.util.Log.d("FLUXUP_DEBUG", "TASK_DATE: " + entry.getKey() + " | COMPLETED_TASKS: " + dp.completedTasks + " | GOAL: " + dp.dailyGoal + " | PERMANENT: " + dp.isGoalReached); completedDatesThisMonth.add(dp.date);
String[] parts = entry.getKey().split("-"); String[] parts = dp.date.split("-");
if (parts.length == 3) { if (parts.length == 3) {
int y = Integer.parseInt(parts[0]);
int m = Integer.parseInt(parts[1]) - 1; // Calendar.MONTH is 0-indexed
int d = Integer.parseInt(parts[2]); int d = Integer.parseInt(parts[2]);
if (y == year && m == month) {
dailyProgressMap.put(d, dp); dailyProgressMap.put(d, dp);
} }
} }
// MERGE com dias_concluidos do objeto user para retrocompatibilidade/consistência
if (currentUserObj != null && currentUserObj.dias_concluidos != null) {
String monthPrefix = String.format(Locale.US, "%04d-%02d-", year, month + 1);
for (String date : currentUserObj.dias_concluidos) {
if (date.startsWith(monthPrefix)) {
completedDatesThisMonth.add(date);
}
}
} }
android.util.Log.d("FLUXUP_DEBUG", "COMPLETED_DAYS_COUNT: " + completedDatesThisMonth.size());
// Aplicar o fallback seguro para HOJE usando o tasks_concluidas_hoje do utilizador // Aplicar o fallback seguro para HOJE usando o tasks_concluidas_hoje do utilizador
// devido a potenciais atrasos na indexação dos xp_logs com serverTimestamp
Calendar todayCal = Calendar.getInstance(); Calendar todayCal = Calendar.getInstance();
if (todayCal.get(Calendar.YEAR) == year && todayCal.get(Calendar.MONTH) == month) { if (todayCal.get(Calendar.YEAR) == year && todayCal.get(Calendar.MONTH) == month) {
int todayDay = todayCal.get(Calendar.DAY_OF_MONTH); int todayDay = todayCal.get(Calendar.DAY_OF_MONTH);
DailyProgress dpToday = dailyProgressMap.get(todayDay); DailyProgress dpToday = dailyProgressMap.get(todayDay);
if (dpToday == null) { if (dpToday == null) {
dpToday = new DailyProgress(year + "-" + (month + 1) + "-" + todayDay, currentDailyGoal); dpToday = new DailyProgress(String.format(Locale.US, "%04d-%02d-%02d", year, month + 1, todayDay), currentDailyGoal);
dailyProgressMap.put(todayDay, dpToday); dailyProgressMap.put(todayDay, dpToday);
} }
int userObjectToday = (currentUserObj != null) ? currentUserObj.tasks_concluidas_hoje : 0; int userObjectToday = (currentUserObj != null) ? currentUserObj.tasks_concluidas_hoje : 0;
dpToday.completedTasks = Math.max(dpToday.completedTasks, userObjectToday); dpToday.completedTasks = Math.max(dpToday.completedTasks, userObjectToday);
dpToday.updateStatus(); dpToday.updateStatus();
}
// Contar quantos dias no mês atingiram a meta if (dpToday.isCompleted) {
int completedDaysCount = 0; completedDatesThisMonth.add(dpToday.date);
Calendar calcCal = (Calendar) currentCalendar.clone();
int maxDaysInMonth = calcCal.getActualMaximum(Calendar.DAY_OF_MONTH);
for (int d = 1; d <= maxDaysInMonth; d++) {
DailyProgress dp = dailyProgressMap.get(d);
if (dp != null) {
dp.updateStatus();
boolean isComplete = "complete".equals(dp.status);
if (isComplete) {
completedDaysCount++;
}
if (d == 6 || d == 11) {
android.util.Log.d("FLUXUP_DEBUG", "DAY_" + d + "_COMPLETED_TASKS: " + dp.completedTasks);
android.util.Log.d("FLUXUP_DEBUG", "DAY_" + d + "_IS_COMPLETED: " + isComplete);
}
} }
} }
android.util.Log.d("FLUXUP_DEBUG", "DIAS_CUMPRIDOS_COUNT: " + completedDaysCount); // Mostrar total de dias concluídos (Histórico Real do Mês)
tvDaysOfPractice.setText(String.valueOf(completedDaysCount)); int diasCumpridos = completedDatesThisMonth.size();
android.util.Log.d("FLUXUP_DEBUG", "DIAS_CUMPRIDOS_VALUE: " + diasCumpridos);
tvDaysOfPractice.setText(String.valueOf(diasCumpridos));
tvFocusSessions.setText(String.valueOf(focusSessionsCount)); tvFocusSessions.setText(String.valueOf(focusSessionsCount));
updateCalendar(dailyProgressMap); updateCalendar(dailyProgressMap);
@@ -231,16 +230,23 @@ public class StreakActivity extends AppCompatActivity {
} }
} }
// Regra: status do DailyProgress (respeita a meta permanente se existir) // Regra: Histórico Persistente
DailyProgress dp = dailyProgressMap.get(i); DailyProgress dp = dailyProgressMap.get(i);
String dateKey = String.format(Locale.US, "%04d-%02d-%02d", calYear, calMonth + 1, i);
String status = "empty"; String status = "empty";
if (dp != null) {
if (currentUserObj != null && currentUserObj.dias_concluidos != null && currentUserObj.dias_concluidos.contains(dateKey)) {
status = "complete";
} else if (dp != null) {
dp.updateStatus(); dp.updateStatus();
status = dp.status; status = dp.status;
} }
if (i == 6 && isCurrentMonth) { if (i == 11 && isCurrentMonth) {
android.util.Log.d("FLUXUP_DEBUG", "DAY_6_STATUS: " + status); android.util.Log.d("FLUXUP_DEBUG", "DAY_11_STATUS: " + status);
}
if (i == 12 && isCurrentMonth) {
android.util.Log.d("FLUXUP_DEBUG", "DAY_12_STATUS: " + status);
} }
days.add(new CalendarDay(i, dp != null ? dp.completedTasks : 0, isCurrent, isFuture, status)); days.add(new CalendarDay(i, dp != null ? dp.completedTasks : 0, isCurrent, isFuture, status));

View File

@@ -37,6 +37,7 @@ public class Usuario {
public String last_streak_completed_date = ""; // YYYY-MM-DD public String last_streak_completed_date = ""; // YYYY-MM-DD
public String last_reward_claim_date = ""; // YYYY-MM-DD public String last_reward_claim_date = ""; // YYYY-MM-DD
public String avatar_url = ""; public String avatar_url = "";
public java.util.List<String> dias_concluidos = new java.util.ArrayList<>();
public Usuario() {} public Usuario() {}

View File

@@ -71,8 +71,7 @@ public class UsuariosService {
android.util.Log.d("FLUXUP_SERVICE", "A guardar utilizador no Firestore (Coleção: users, ID: " + uid + ")..."); android.util.Log.d("FLUXUP_SERVICE", "A guardar utilizador no Firestore (Coleção: users, ID: " + uid + ")...");
getFirestore().collection("users").document(uid).set(usuario) getFirestore().collection("users").document(uid).set(usuario)
.addOnSuccessListener(aVoid -> { .addOnSuccessListener(aVoid -> {
android.util.Log.d("FLUXUP_SERVICE", "Utilizador guardado no Firestore com sucesso. A criar tarefas iniciais..."); android.util.Log.d("FLUXUP_SERVICE", "Utilizador guardado no Firestore com sucesso.");
createInitialTasks(uid);
usuario.palavra_passe = tempPass; usuario.palavra_passe = tempPass;
callback.onSuccess(usuario); callback.onSuccess(usuario);
}) })
@@ -90,18 +89,6 @@ public class UsuariosService {
}); });
} }
private static void createInitialTasks(String uid) {
String[] defaultTasks = {
"Completar o perfil",
"Iniciar primeira sessão de foco",
"Definir objetivo diário"
};
for (String title : defaultTasks) {
String taskId = getFirestore().collection("tasks").document().getId();
Task task = new Task(taskId, title, 50, 25, uid);
getFirestore().collection("tasks").document(taskId).set(task);
}
}
public static void recuperarPalavraPasse(Context context, String email, ServiceCallback<Void> callback) { public static void recuperarPalavraPasse(Context context, String email, ServiceCallback<Void> callback) {
FirebaseAuth.getInstance().sendPasswordResetEmail(email) FirebaseAuth.getInstance().sendPasswordResetEmail(email)