erro ao realizar a tarefa
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
<activity android:name=".StatisticsActivity" />
|
<activity android:name=".StatisticsActivity" />
|
||||||
<activity android:name=".FindFriendsActivity" />
|
<activity android:name=".FindFriendsActivity" />
|
||||||
<activity android:name=".TrophiesActivity" />
|
<activity android:name=".TrophiesActivity" />
|
||||||
|
<activity android:name=".MyFriendsActivity" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ import android.os.Bundle;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|||||||
@@ -24,6 +24,18 @@ public class FirestoreManager {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtém os dados do utilizador uma única vez.
|
||||||
|
*/
|
||||||
|
public void getUser(String uid, Consumer<Usuario> callback) {
|
||||||
|
db.collection("users").document(uid).get().addOnSuccessListener(snapshot -> {
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
Usuario user = snapshot.toObject(Usuario.class);
|
||||||
|
if (user != null) callback.accept(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observa as mudanças no documento do utilizador em tempo real.
|
* Observa as mudanças no documento do utilizador em tempo real.
|
||||||
*/
|
*/
|
||||||
@@ -83,4 +95,16 @@ public class FirestoreManager {
|
|||||||
public void updateUserStats(String uid, Map<String, Object> updates) {
|
public void updateUserStats(String uid, Map<String, Object> updates) {
|
||||||
db.collection("users").document(uid).update(updates);
|
db.collection("users").document(uid).update(updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regista um log de XP.
|
||||||
|
*/
|
||||||
|
public void addXpLog(String uid, int amount, String type) {
|
||||||
|
Map<String, Object> log = new java.util.HashMap<>();
|
||||||
|
log.put("userId", uid);
|
||||||
|
log.put("amount", amount);
|
||||||
|
log.put("type", type);
|
||||||
|
log.put("created_at", com.google.firebase.firestore.FieldValue.serverTimestamp());
|
||||||
|
db.collection("xp_logs").add(log);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
import com.google.firebase.auth.FirebaseUser;
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
import com.google.firebase.firestore.ListenerRegistration;
|
import com.google.firebase.firestore.ListenerRegistration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -28,6 +29,7 @@ import java.util.Calendar;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
|
||||||
public class InicioFragment extends Fragment {
|
public class InicioFragment extends Fragment {
|
||||||
@@ -36,7 +38,9 @@ public class InicioFragment extends Fragment {
|
|||||||
private TextView tvTodayStreak, tvTodayXP, tvTodayTasksCount, tvNoTasksIncentive;
|
private TextView tvTodayStreak, tvTodayXP, tvTodayTasksCount, tvNoTasksIncentive;
|
||||||
private TextView tvDailyRewardGoal;
|
private TextView tvDailyRewardGoal;
|
||||||
private ProgressBar pbDailyTasksProgress;
|
private ProgressBar pbDailyTasksProgress;
|
||||||
private LinearLayout tasksContainer, miniRankingContainer;
|
private androidx.recyclerview.widget.RecyclerView rvTasks;
|
||||||
|
private TasksAdapter tasksAdapter;
|
||||||
|
private LinearLayout miniRankingContainer, layoutTasksSection;
|
||||||
private Button btnStartFocus, btnAddTasks, btnClaimReward;
|
private Button btnStartFocus, btnAddTasks, btnClaimReward;
|
||||||
|
|
||||||
private CountDownTimer countDownTimer;
|
private CountDownTimer countDownTimer;
|
||||||
@@ -56,7 +60,10 @@ public class InicioFragment extends Fragment {
|
|||||||
"Um passo de cada vez.",
|
"Um passo de cada vez.",
|
||||||
"A consistência é a chave.",
|
"A consistência é a chave.",
|
||||||
"Foca no progresso, não na perfeição.",
|
"Foca no progresso, não na perfeição.",
|
||||||
"Hoje é um ótimo dia para ser produtivo!"
|
"Hoje é um ótimo dia para ser produtivo!",
|
||||||
|
"Vence a procrastinação agora.",
|
||||||
|
"A tua versão do futuro vai agradecer.",
|
||||||
|
"Pequenos passos, grandes resultados."
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +77,10 @@ public class InicioFragment extends Fragment {
|
|||||||
tvMotivationalSubtitle = view.findViewById(R.id.tvMotivationalSubtitle);
|
tvMotivationalSubtitle = view.findViewById(R.id.tvMotivationalSubtitle);
|
||||||
view.findViewById(R.id.cardProfileAvatar).setOnClickListener(v -> {
|
view.findViewById(R.id.cardProfileAvatar).setOnClickListener(v -> {
|
||||||
if (getActivity() instanceof MainActivity) {
|
if (getActivity() instanceof MainActivity) {
|
||||||
((MainActivity) getActivity()).findViewById(R.id.nav_profile).performClick();
|
BottomNavigationView nav = ((MainActivity) getActivity()).findViewById(R.id.bottom_navigation);
|
||||||
|
if (nav != null) {
|
||||||
|
nav.setSelectedItemId(R.id.nav_profile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -81,7 +91,17 @@ public class InicioFragment extends Fragment {
|
|||||||
pbDailyTasksProgress = view.findViewById(R.id.pbDailyTasksProgress);
|
pbDailyTasksProgress = view.findViewById(R.id.pbDailyTasksProgress);
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
tasksContainer = view.findViewById(R.id.tasksContainer);
|
layoutTasksSection = view.findViewById(R.id.layoutTasksSection);
|
||||||
|
rvTasks = view.findViewById(R.id.rvTasks);
|
||||||
|
rvTasks.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(getContext()));
|
||||||
|
tasksAdapter = new TasksAdapter(currentTasks, new TasksAdapter.OnTaskClickListener() {
|
||||||
|
@Override public void onTaskFocus(Task task) { selectTaskForFocus(task); }
|
||||||
|
@Override public void onTaskDelete(Task task) { showDeleteConfirmDialog(task); }
|
||||||
|
@Override public void onTaskEdit(Task task) { showEditTaskDialog(task); }
|
||||||
|
});
|
||||||
|
rvTasks.setAdapter(tasksAdapter);
|
||||||
|
setupSwipeToDelete();
|
||||||
|
|
||||||
tvNoTasksIncentive = view.findViewById(R.id.tvNoTasksIncentive);
|
tvNoTasksIncentive = view.findViewById(R.id.tvNoTasksIncentive);
|
||||||
btnAddTasks = view.findViewById(R.id.btnAddTasks);
|
btnAddTasks = view.findViewById(R.id.btnAddTasks);
|
||||||
btnAddTasks.setOnClickListener(v -> showAddTaskDialog());
|
btnAddTasks.setOnClickListener(v -> showAddTaskDialog());
|
||||||
@@ -92,7 +112,9 @@ public class InicioFragment extends Fragment {
|
|||||||
btnStartFocus.setOnClickListener(v -> {
|
btnStartFocus.setOnClickListener(v -> {
|
||||||
if (!isTimerRunning) {
|
if (!isTimerRunning) {
|
||||||
if (selectedTaskForFocus == null) {
|
if (selectedTaskForFocus == null) {
|
||||||
Toast.makeText(getContext(), "Seleciona uma tarefa primeiro!", Toast.LENGTH_SHORT).show();
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), "Seleciona uma tarefa primeiro!", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startTimer();
|
startTimer();
|
||||||
@@ -137,7 +159,11 @@ public class InicioFragment extends Fragment {
|
|||||||
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
tasksListener = FirestoreManager.getInstance().observeTasks(currentUser.getUid(), tasks -> {
|
tasksListener = FirestoreManager.getInstance().observeTasks(currentUser.getUid(), tasks -> {
|
||||||
currentTasks = tasks;
|
List<Task> activeTasks = new ArrayList<>();
|
||||||
|
for (Task t : tasks) {
|
||||||
|
if (!t.completed) activeTasks.add(t);
|
||||||
|
}
|
||||||
|
currentTasks = activeTasks;
|
||||||
updateTasksUI();
|
updateTasksUI();
|
||||||
updateTodayCard();
|
updateTodayCard();
|
||||||
});
|
});
|
||||||
@@ -159,131 +185,157 @@ public class InicioFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update Reward Button State
|
// Update Reward Button State
|
||||||
if (user.tasks_concluidas_hoje >= user.meta_diaria_tarefas) {
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
||||||
|
boolean alreadyClaimed = today.equals(user.last_reward_claim_date);
|
||||||
|
|
||||||
|
if (user.tasks_concluidas_hoje >= user.meta_diaria_tarefas && !alreadyClaimed) {
|
||||||
btnClaimReward.setEnabled(true);
|
btnClaimReward.setEnabled(true);
|
||||||
btnClaimReward.setAlpha(1.0f);
|
btnClaimReward.setAlpha(1.0f);
|
||||||
|
btnClaimReward.setText("Resgatar");
|
||||||
|
} else if (alreadyClaimed) {
|
||||||
|
btnClaimReward.setEnabled(false);
|
||||||
|
btnClaimReward.setAlpha(0.5f);
|
||||||
|
btnClaimReward.setText("Resgatado");
|
||||||
} else {
|
} else {
|
||||||
btnClaimReward.setEnabled(false);
|
btnClaimReward.setEnabled(false);
|
||||||
btnClaimReward.setAlpha(0.5f);
|
btnClaimReward.setAlpha(0.5f);
|
||||||
|
btnClaimReward.setText("Resgatar");
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDailyReset(user);
|
updateTodayCard(user);
|
||||||
|
checkDailyResetAndStreak(user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTasksUI() {
|
private void updateTasksUI() {
|
||||||
if (getContext() == null || tasksContainer == null) return;
|
if (tasksAdapter != null) {
|
||||||
tasksContainer.removeAllViews();
|
tasksAdapter.setTasks(currentTasks);
|
||||||
|
|
||||||
for (Task task : currentTasks) {
|
|
||||||
View taskView = LayoutInflater.from(getContext()).inflate(R.layout.item_task_home, tasksContainer, false);
|
|
||||||
|
|
||||||
TextView tvTitle = taskView.findViewById(R.id.tvTaskTitle);
|
|
||||||
TextView tvDuration = taskView.findViewById(R.id.tvTaskDuration);
|
|
||||||
CheckBox cb = taskView.findViewById(R.id.cbTask);
|
|
||||||
Button btnStart = taskView.findViewById(R.id.btnStartTaskFocus);
|
|
||||||
|
|
||||||
tvTitle.setText(task.title);
|
|
||||||
tvDuration.setText(task.duration + " min");
|
|
||||||
cb.setChecked(task.completed);
|
|
||||||
|
|
||||||
if (task.completed) {
|
|
||||||
tvTitle.setPaintFlags(tvTitle.getPaintFlags() | android.graphics.Paint.STRIKE_THRU_TEXT_FLAG);
|
|
||||||
tvTitle.setTextColor(getResources().getColor(R.color.text_secondary));
|
|
||||||
btnStart.setEnabled(false);
|
|
||||||
btnStart.setAlpha(0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
|
||||||
if (isChecked && !task.completed) {
|
|
||||||
completeTask(task);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
btnStart.setOnClickListener(v -> {
|
|
||||||
selectedTaskForFocus = task;
|
|
||||||
timeLeftInMillis = task.duration * 60 * 1000;
|
|
||||||
updateCountDownText();
|
|
||||||
Toast.makeText(getContext(), "Tarefa selecionada: " + task.title, Toast.LENGTH_SHORT).show();
|
|
||||||
|
|
||||||
// Highlight selection
|
|
||||||
for (int i = 0; i < tasksContainer.getChildCount(); i++) {
|
|
||||||
tasksContainer.getChildAt(i).setBackground(null);
|
|
||||||
}
|
|
||||||
taskView.setBackgroundResource(R.drawable.task_selected_bg);
|
|
||||||
});
|
|
||||||
|
|
||||||
taskView.setOnLongClickListener(v -> {
|
|
||||||
showDeleteConfirmDialog(task);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
tasksContainer.addView(taskView);
|
|
||||||
}
|
}
|
||||||
updateTodayCard();
|
updateTodayCard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectTaskForFocus(Task task) {
|
||||||
|
selectedTaskForFocus = task;
|
||||||
|
timeLeftInMillis = task.duration * 60 * 1000;
|
||||||
|
updateCountDownText();
|
||||||
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), "Modo Foco: " + task.title, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSwipeToDelete() {
|
||||||
|
new androidx.recyclerview.widget.ItemTouchHelper(new androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback(0, androidx.recyclerview.widget.ItemTouchHelper.LEFT | androidx.recyclerview.widget.ItemTouchHelper.RIGHT) {
|
||||||
|
@Override
|
||||||
|
public boolean onMove(@NonNull androidx.recyclerview.widget.RecyclerView recyclerView, @NonNull androidx.recyclerview.widget.RecyclerView.ViewHolder viewHolder, @NonNull androidx.recyclerview.widget.RecyclerView.ViewHolder target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwiped(@NonNull androidx.recyclerview.widget.RecyclerView.ViewHolder viewHolder, int direction) {
|
||||||
|
int position = viewHolder.getAdapterPosition();
|
||||||
|
Task task = currentTasks.get(position);
|
||||||
|
showDeleteConfirmDialog(task);
|
||||||
|
tasksAdapter.notifyItemChanged(position); // Revert swipe if canceled? Firestore update will refresh anyway.
|
||||||
|
}
|
||||||
|
}).attachToRecyclerView(rvTasks);
|
||||||
|
}
|
||||||
|
|
||||||
private void addXP(int amount) {
|
private void addXP(int amount) {
|
||||||
|
if (!isAdded()) return;
|
||||||
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
|
String uid = currentUser.getUid();
|
||||||
Map<String, Object> updates = new HashMap<>();
|
Map<String, Object> updates = new HashMap<>();
|
||||||
updates.put("xp", com.google.firebase.firestore.FieldValue.increment(amount));
|
updates.put("xp", com.google.firebase.firestore.FieldValue.increment(amount));
|
||||||
updates.put("xp_hoje", com.google.firebase.firestore.FieldValue.increment(amount));
|
updates.put("xp_hoje", com.google.firebase.firestore.FieldValue.increment(amount));
|
||||||
|
updates.put("xp_semanal", com.google.firebase.firestore.FieldValue.increment(amount));
|
||||||
|
|
||||||
// Check Level Up logic inside observe once
|
FirestoreManager.getInstance().getUser(uid, user -> {
|
||||||
com.google.firebase.firestore.FirebaseFirestore.getInstance()
|
if (user != null && isAdded()) {
|
||||||
.collection("users").document(currentUser.getUid()).get()
|
int currentLevel = user.level;
|
||||||
.addOnSuccessListener(snapshot -> {
|
int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
|
||||||
Usuario user = snapshot.toObject(Usuario.class);
|
if (user.xp + amount >= threshold) {
|
||||||
if (user != null) {
|
updates.put("level", currentLevel + 1);
|
||||||
int currentLevel = user.level;
|
showLevelUpAnimation(currentLevel + 1);
|
||||||
int nextLevelThreshold = currentLevel * 500;
|
|
||||||
if (user.xp + amount >= nextLevelThreshold) {
|
|
||||||
updates.put("level", currentLevel + 1);
|
|
||||||
showLevelUpAnimation(currentLevel + 1);
|
|
||||||
}
|
|
||||||
FirestoreManager.getInstance().updateUserStats(currentUser.getUid(), updates);
|
|
||||||
}
|
}
|
||||||
});
|
FirestoreManager.getInstance().updateUserStats(uid, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTodayCard() {
|
private void updateTodayCard() {
|
||||||
int total = currentTasks.size();
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||||
int completed = 0;
|
if (currentUser != null) {
|
||||||
for (Task task : currentTasks) {
|
FirestoreManager.getInstance().getUser(currentUser.getUid(), this::updateTodayCard);
|
||||||
if (task.completed) completed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tvTodayTasksCount != null) {
|
|
||||||
tvTodayTasksCount.setText(completed + "/" + (total == 0 ? 3 : total));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pbDailyTasksProgress != null) {
|
|
||||||
int progress = (total == 0) ? 0 : (completed * 100) / total;
|
|
||||||
pbDailyTasksProgress.setProgress(progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (total == 0) {
|
|
||||||
tvNoTasksIncentive.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
tvNoTasksIncentive.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkDailyReset(Usuario user) {
|
private void updateTodayCard(Usuario user) {
|
||||||
|
int completed = user.tasks_concluidas_hoje;
|
||||||
|
int goal = user.meta_diaria_tarefas;
|
||||||
|
if (goal <= 0) goal = 3; // Default fallback
|
||||||
|
|
||||||
|
if (tvTodayTasksCount != null) {
|
||||||
|
tvTodayTasksCount.setText(completed + "/" + goal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbDailyTasksProgress != null) {
|
||||||
|
int progress = (completed * 100) / goal;
|
||||||
|
if (progress > 100) progress = 100;
|
||||||
|
pbDailyTasksProgress.setProgress(progress);
|
||||||
|
updatePathProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTasks != null && tvNoTasksIncentive != null && layoutTasksSection != null) {
|
||||||
|
if (currentTasks.isEmpty()) {
|
||||||
|
tvNoTasksIncentive.setVisibility(View.VISIBLE);
|
||||||
|
layoutTasksSection.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
tvNoTasksIncentive.setVisibility(View.GONE);
|
||||||
|
layoutTasksSection.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDailyResetAndStreak(Usuario user) {
|
||||||
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
||||||
if (!today.equals(user.last_active_date)) {
|
if (!today.equals(user.last_active_date)) {
|
||||||
Map<String, Object> updates = new HashMap<>();
|
Map<String, Object> updates = new HashMap<>();
|
||||||
if (user.tasks_concluidas_hoje == 0 && !user.last_active_date.isEmpty()) {
|
|
||||||
updates.put("streak", 0);
|
// Streak logic
|
||||||
|
if (!user.last_active_date.isEmpty()) {
|
||||||
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||||
|
try {
|
||||||
|
java.util.Date lastDate = sdf.parse(user.last_active_date);
|
||||||
|
java.util.Date todayDate = sdf.parse(today);
|
||||||
|
long diff = (todayDate.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
|
if (diff == 1) {
|
||||||
|
// Successive day, but wait for first task completion to increment streak?
|
||||||
|
// Or increment now if they at least logged in? User said "Completar pelo menos 1 tarefa por dia -> streak +1"
|
||||||
|
// So we don't increment here, we just check if we should reset.
|
||||||
|
} else if (diff > 1) {
|
||||||
|
// Failed a day
|
||||||
|
updates.put("streak", 0);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updates.put("xp_hoje", 0);
|
updates.put("xp_hoje", 0);
|
||||||
updates.put("tasks_concluidas_hoje", 0);
|
updates.put("tasks_concluidas_hoje", 0);
|
||||||
updates.put("tempo_foco_hoje", 0);
|
updates.put("tempo_foco_hoje", 0);
|
||||||
updates.put("last_active_date", today);
|
updates.put("last_active_date", today);
|
||||||
FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates);
|
FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates);
|
||||||
|
|
||||||
|
// Login reward
|
||||||
|
addXP(10);
|
||||||
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), "Recompensa de login: +10 XP!", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,14 +358,23 @@ public class InicioFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addMiniRankingItem(int rank, String name, int xp) {
|
private void addMiniRankingItem(int rank, String name, int xp) {
|
||||||
View item = getLayoutInflater().inflate(android.R.layout.simple_list_item_2, miniRankingContainer, false);
|
if (getContext() == null || miniRankingContainer == null) return;
|
||||||
TextView tv1 = item.findViewById(android.R.id.text1);
|
|
||||||
TextView tv2 = item.findViewById(android.R.id.text2);
|
View item = getLayoutInflater().inflate(R.layout.item_ranking_user, miniRankingContainer, false);
|
||||||
tv1.setText(rank + ". " + name);
|
TextView tvRank = item.findViewById(R.id.tvRankPosition);
|
||||||
tv1.setTextSize(14);
|
TextView tvName = item.findViewById(R.id.tvRankingName);
|
||||||
tv1.setTextColor(getResources().getColor(R.color.text_primary));
|
TextView tvXP = item.findViewById(R.id.tvRankingXP);
|
||||||
tv2.setText(xp + " XP hoje");
|
|
||||||
tv2.setTextSize(12);
|
tvRank.setText("#" + rank);
|
||||||
|
tvName.setText(name);
|
||||||
|
tvXP.setText(xp + " XP");
|
||||||
|
|
||||||
|
// Remove elevation for mini ranking to keep it clean
|
||||||
|
if (item instanceof androidx.cardview.widget.CardView) {
|
||||||
|
((androidx.cardview.widget.CardView) item).setCardElevation(0);
|
||||||
|
((androidx.cardview.widget.CardView) item).setCardBackgroundColor(android.graphics.Color.TRANSPARENT);
|
||||||
|
}
|
||||||
|
|
||||||
miniRankingContainer.addView(item);
|
miniRankingContainer.addView(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,15 +414,19 @@ public class InicioFragment extends Fragment {
|
|||||||
if (i < currentDayIndex) {
|
if (i < currentDayIndex) {
|
||||||
// Past day - Assume completed for demo
|
// Past day - Assume completed for demo
|
||||||
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
|
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
|
||||||
nodeCircle.getBackground().setTint(getResources().getColor(R.color.success_green));
|
if (getContext() != null) {
|
||||||
nodeDayInitial.setTextColor(getResources().getColor(R.color.white));
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.success_green));
|
||||||
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.white));
|
||||||
|
}
|
||||||
nodeProgress.setVisibility(View.GONE);
|
nodeProgress.setVisibility(View.GONE);
|
||||||
} else if (i == currentDayIndex) {
|
} else if (i == currentDayIndex) {
|
||||||
// Today
|
// Today
|
||||||
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
|
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
|
||||||
nodeCircle.getBackground().setTint(getResources().getColor(R.color.primary_purple));
|
if (getContext() != null) {
|
||||||
nodeDayInitial.setTextColor(getResources().getColor(R.color.white));
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
||||||
nodeDayLabel.setTextColor(getResources().getColor(R.color.primary_purple));
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.white));
|
||||||
|
nodeDayLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
||||||
|
}
|
||||||
nodeProgress.setVisibility(View.VISIBLE);
|
nodeProgress.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// Future
|
// Future
|
||||||
@@ -377,30 +442,31 @@ public class InicioFragment extends Fragment {
|
|||||||
private void completeTask(Task task) {
|
private void completeTask(Task task) {
|
||||||
task.completed = true;
|
task.completed = true;
|
||||||
FirestoreManager.getInstance().updateTask(task);
|
FirestoreManager.getInstance().updateTask(task);
|
||||||
addXP(30);
|
|
||||||
updateUserTaskCount();
|
updateUserTaskCount();
|
||||||
boolean allDone = true;
|
|
||||||
for (Task t : currentTasks) {
|
|
||||||
if (!t.completed && !t.id.equals(task.id)) {
|
|
||||||
allDone = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allDone && currentTasks.size() > 0) {
|
|
||||||
addXP(20);
|
|
||||||
Toast.makeText(getContext(), "Todas as tarefas concluídas! +20 XP Bónus", Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
triggerVibration();
|
triggerVibration();
|
||||||
showXpPopup("+30 XP");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUserTaskCount() {
|
private void updateUserTaskCount() {
|
||||||
|
if (!isAdded()) return;
|
||||||
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
Map<String, Object> updates = new HashMap<>();
|
String uid = currentUser.getUid();
|
||||||
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
FirestoreManager.getInstance().getUser(uid, user -> {
|
||||||
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
if (user != null && isAdded()) {
|
||||||
FirestoreManager.getInstance().updateUserStats(currentUser.getUid(), updates);
|
Map<String, Object> updates = new HashMap<>();
|
||||||
|
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
|
||||||
|
if (user.tasks_concluidas_hoje == 0) {
|
||||||
|
updates.put("streak", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
if (user.streak + 1 > user.melhor_streak) {
|
||||||
|
updates.put("melhor_streak", user.streak + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FirestoreManager.getInstance().updateUserStats(uid, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,10 +487,13 @@ public class InicioFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showXpPopup(String text) {
|
private void showXpPopup(String text) {
|
||||||
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerVibration() {
|
private void triggerVibration() {
|
||||||
|
if (getContext() == null) return;
|
||||||
android.os.Vibrator v = (android.os.Vibrator) getContext().getSystemService(android.content.Context.VIBRATOR_SERVICE);
|
android.os.Vibrator v = (android.os.Vibrator) getContext().getSystemService(android.content.Context.VIBRATOR_SERVICE);
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
@@ -436,10 +505,22 @@ public class InicioFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void claimDailyReward() {
|
private void claimDailyReward() {
|
||||||
addXP(100);
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||||
btnClaimReward.setEnabled(false);
|
if (currentUser != null) {
|
||||||
btnClaimReward.setText("Resgatado");
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
||||||
Toast.makeText(getContext(), "Recompensa diária resgatada! +100 XP", Toast.LENGTH_LONG).show();
|
Map<String, Object> updates = new HashMap<>();
|
||||||
|
updates.put("last_reward_claim_date", today);
|
||||||
|
FirestoreManager.getInstance().updateUserStats(currentUser.getUid(), updates);
|
||||||
|
addXP(100);
|
||||||
|
|
||||||
|
btnClaimReward.setEnabled(false);
|
||||||
|
btnClaimReward.setText("Resgatado");
|
||||||
|
btnClaimReward.setAlpha(0.5f);
|
||||||
|
|
||||||
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), "Recompensa diária resgatada! +100 XP", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDeleteConfirmDialog(Task task) {
|
private void showDeleteConfirmDialog(Task task) {
|
||||||
@@ -459,11 +540,11 @@ public class InicioFragment extends Fragment {
|
|||||||
ProgressBar nodeProgress = todayNode.findViewById(R.id.nodeProgress);
|
ProgressBar nodeProgress = todayNode.findViewById(R.id.nodeProgress);
|
||||||
View nodeCircle = todayNode.findViewById(R.id.nodeCircle);
|
View nodeCircle = todayNode.findViewById(R.id.nodeCircle);
|
||||||
if (nodeProgress != null) nodeProgress.setProgress(progress);
|
if (nodeProgress != null) nodeProgress.setProgress(progress);
|
||||||
if (progress == 100) {
|
if (progress == 100 && getContext() != null) {
|
||||||
nodeCircle.getBackground().setTint(getResources().getColor(R.color.success_green));
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.success_green));
|
||||||
triggerSuccessAnimation(todayNode);
|
triggerSuccessAnimation(todayNode);
|
||||||
} else {
|
} else if (getContext() != null) {
|
||||||
nodeCircle.getBackground().setTint(getResources().getColor(R.color.primary_purple));
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +558,9 @@ public class InicioFragment extends Fragment {
|
|||||||
animatorSet.playTogether(scaleX, scaleY);
|
animatorSet.playTogether(scaleX, scaleY);
|
||||||
animatorSet.start();
|
animatorSet.start();
|
||||||
|
|
||||||
Toast.makeText(getContext(), "Dia Completado! 🎉", Toast.LENGTH_SHORT).show();
|
if (getContext() != null) {
|
||||||
|
Toast.makeText(getContext(), "Dia Completado! 🎉", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -491,19 +574,123 @@ public class InicioFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onFinish() {
|
public void onFinish() {
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_FINISHED_START");
|
||||||
isTimerRunning = false;
|
isTimerRunning = false;
|
||||||
btnStartFocus.setText("Começar Foco");
|
|
||||||
completeTask(selectedTaskForFocus);
|
if (getActivity() != null && isAdded()) {
|
||||||
addXP(50);
|
btnStartFocus.setText("Começar Foco");
|
||||||
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
}
|
||||||
if (currentUser != null) {
|
|
||||||
Map<String, Object> updates = new HashMap<>();
|
try {
|
||||||
updates.put("tempo_foco_total", com.google.firebase.firestore.FieldValue.increment(selectedTaskForFocus.duration));
|
if (selectedTaskForFocus == null) {
|
||||||
updates.put("tempo_foco_hoje", com.google.firebase.firestore.FieldValue.increment(selectedTaskForFocus.duration));
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_FINISHED_ERROR: selectedTask is null");
|
||||||
updates.put("sessoes_foco_completas", com.google.firebase.firestore.FieldValue.increment(1));
|
return;
|
||||||
FirestoreManager.getInstance().updateUserStats(currentUser.getUid(), updates);
|
}
|
||||||
|
|
||||||
|
String taskId = selectedTaskForFocus.id;
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "TASK_ID: " + taskId);
|
||||||
|
|
||||||
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||||
|
if (currentUser == null) {
|
||||||
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_FINISHED_ERROR: USER_ID is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String userId = currentUser.getUid();
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "USER_ID: " + userId);
|
||||||
|
|
||||||
|
if (taskId == null || taskId.isEmpty()) {
|
||||||
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_FINISHED_ERROR: task.id is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Início da sincronização segura
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_START");
|
||||||
|
|
||||||
|
FirestoreManager.getInstance().getUser(userId, user -> {
|
||||||
|
if (user == null) {
|
||||||
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: User data is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isAdded()) return;
|
||||||
|
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + taskId);
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "USER_ID: " + userId);
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "XP_BEFORE: " + user.xp_hoje);
|
||||||
|
|
||||||
|
// 1. Log de XP
|
||||||
|
Map<String, Object> log = new HashMap<>();
|
||||||
|
log.put("userId", userId);
|
||||||
|
log.put("amount", 50);
|
||||||
|
log.put("type", "focus_task");
|
||||||
|
log.put("created_at", com.google.firebase.firestore.FieldValue.serverTimestamp());
|
||||||
|
|
||||||
|
com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("xp_logs")
|
||||||
|
.add(log)
|
||||||
|
.addOnSuccessListener(ref -> android.util.Log.d("FLUXUP_DEBUG", "XP_LOG_INSERT_RESULT: SUCCESS"))
|
||||||
|
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "XP_LOG_INSERT_RESULT: FAIL - " + e.getMessage()));
|
||||||
|
|
||||||
|
// 2. Preparar updates consolidados
|
||||||
|
Map<String, Object> updates = new HashMap<>();
|
||||||
|
// Usando os nomes exatos de Usuario.java: xp, xp_hoje, xp_semanal
|
||||||
|
updates.put("xp", com.google.firebase.firestore.FieldValue.increment(50));
|
||||||
|
updates.put("xp_hoje", com.google.firebase.firestore.FieldValue.increment(50));
|
||||||
|
updates.put("xp_semanal", com.google.firebase.firestore.FieldValue.increment(50));
|
||||||
|
|
||||||
|
updates.put("tempo_foco_total", com.google.firebase.firestore.FieldValue.increment(selectedTaskForFocus.duration));
|
||||||
|
updates.put("tempo_foco_hoje", com.google.firebase.firestore.FieldValue.increment(selectedTaskForFocus.duration));
|
||||||
|
updates.put("sessoes_foco_completas", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
|
||||||
|
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
|
||||||
|
if (user.tasks_concluidas_hoje == 0) {
|
||||||
|
updates.put("streak", com.google.firebase.firestore.FieldValue.increment(1));
|
||||||
|
if (user.streak + 1 > user.melhor_streak) {
|
||||||
|
updates.put("melhor_streak", user.streak + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level Up
|
||||||
|
int currentLevel = user.level;
|
||||||
|
int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
|
||||||
|
if (user.xp + 50 >= threshold) {
|
||||||
|
updates.put("level", currentLevel + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Gravar tudo no Backend (User Stats)
|
||||||
|
com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("users").document(userId)
|
||||||
|
.update(updates)
|
||||||
|
.addOnSuccessListener(aVoid -> {
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "USER_XP_UPDATE_RESULT: SUCCESS");
|
||||||
|
if (isAdded()) {
|
||||||
|
android.util.Log.d("FLUXUP_DEBUG", "HOME_REFRESH_RESULT: SUCCESS");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "USER_XP_UPDATE_RESULT: FAIL - " + e.getMessage()));
|
||||||
|
|
||||||
|
// 4. Concluir tarefa no backend
|
||||||
|
selectedTaskForFocus.completed = true;
|
||||||
|
com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("tasks").document(taskId)
|
||||||
|
.set(selectedTaskForFocus)
|
||||||
|
.addOnSuccessListener(aVoid -> android.util.Log.d("FLUXUP_DEBUG", "TASK_UPDATE_RESULT: SUCCESS"))
|
||||||
|
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "TASK_UPDATE_RESULT: FAIL - " + e.getMessage()));
|
||||||
|
|
||||||
|
if (getContext() != null && isAdded()) {
|
||||||
|
Toast.makeText(getContext(), "Boa! Tarefa concluída +50 XP", Toast.LENGTH_LONG).show();
|
||||||
|
triggerVibration();
|
||||||
|
|
||||||
|
selectedTaskForFocus = null;
|
||||||
|
timeLeftInMillis = 25 * 60 * 1000;
|
||||||
|
updateCountDownText();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_FINISHED_ERROR: " + e.getMessage());
|
||||||
|
if (getContext() != null && isAdded()) {
|
||||||
|
Toast.makeText(getContext(), "Erro ao concluir tarefa. Tenta novamente.", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
selectedTaskForFocus = null;
|
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
isTimerRunning = true;
|
isTimerRunning = true;
|
||||||
@@ -543,6 +730,30 @@ public class InicioFragment extends Fragment {
|
|||||||
if (countDownTimer != null) countDownTimer.cancel();
|
if (countDownTimer != null) countDownTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showEditTaskDialog(Task task) {
|
||||||
|
View dialogView = getLayoutInflater().inflate(R.layout.dialog_add_task, null);
|
||||||
|
android.widget.EditText etTitle = dialogView.findViewById(R.id.etTaskTitle);
|
||||||
|
android.widget.EditText etDuration = dialogView.findViewById(R.id.etTaskDuration);
|
||||||
|
|
||||||
|
etTitle.setText(task.title);
|
||||||
|
etDuration.setText(String.valueOf(task.duration));
|
||||||
|
|
||||||
|
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
||||||
|
.setTitle("Editar Tarefa")
|
||||||
|
.setView(dialogView)
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.setPositiveButton("Atualizar", (dialog, which) -> {
|
||||||
|
String title = etTitle.getText().toString().trim();
|
||||||
|
String durationStr = etDuration.getText().toString().trim();
|
||||||
|
if (!title.isEmpty()) {
|
||||||
|
task.title = title;
|
||||||
|
if (!durationStr.isEmpty()) task.duration = Integer.parseInt(durationStr);
|
||||||
|
FirestoreManager.getInstance().updateTask(task);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void showAddTaskDialog() {
|
private void showAddTaskDialog() {
|
||||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_add_task, null);
|
View dialogView = getLayoutInflater().inflate(R.layout.dialog_add_task, null);
|
||||||
android.widget.EditText etTitle = dialogView.findViewById(R.id.etTaskTitle);
|
android.widget.EditText etTitle = dialogView.findViewById(R.id.etTaskTitle);
|
||||||
@@ -564,7 +775,14 @@ public class InicioFragment extends Fragment {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int duration = 25;
|
int duration = 25;
|
||||||
if (!durationStr.isEmpty()) duration = Integer.parseInt(durationStr);
|
if (!durationStr.isEmpty()) {
|
||||||
|
try {
|
||||||
|
duration = Integer.parseInt(durationStr);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
etDuration.setError("Inválido");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
saveNewTask(title, duration);
|
saveNewTask(title, duration);
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.GridLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import com.google.firebase.auth.FirebaseUser;
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
import com.google.firebase.firestore.ListenerRegistration;
|
import com.google.firebase.firestore.ListenerRegistration;
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
|
|
||||||
view.findViewById(R.id.btnManageFriends).setOnClickListener(v -> {
|
view.findViewById(R.id.btnManageFriends).setOnClickListener(v -> {
|
||||||
startActivity(new Intent(getActivity(), FindFriendsActivity.class));
|
startActivity(new Intent(getActivity(), MyFriendsActivity.class));
|
||||||
});
|
});
|
||||||
|
|
||||||
view.findViewById(R.id.btnViewStatsDetails).setOnClickListener(v -> {
|
view.findViewById(R.id.btnViewStatsDetails).setOnClickListener(v -> {
|
||||||
@@ -57,7 +59,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
|
|
||||||
view.findViewById(R.id.btnLogout).setOnClickListener(v -> {
|
view.findViewById(R.id.btnLogout).setOnClickListener(v -> {
|
||||||
AuthManager.getInstance().signOut();
|
AuthManager.getInstance().logout();
|
||||||
Intent intent = new Intent(getActivity(), LoginActivity.class);
|
Intent intent = new Intent(getActivity(), LoginActivity.class);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
@@ -103,13 +105,17 @@ public class ProfileFragment extends Fragment {
|
|||||||
|
|
||||||
private void renderBadges(Usuario user) {
|
private void renderBadges(Usuario user) {
|
||||||
badgesGrid.removeAllViews();
|
badgesGrid.removeAllViews();
|
||||||
if (user.streak >= 7) addBadge("🔥", "Semana Ativa");
|
// 7 days streak
|
||||||
if (user.total_tasks_concluidas >= 50) addBadge("🏆", "Executor");
|
addBadge(user.streak >= 7 ? "🔥" : "🔒", "7 Dias", user.streak >= 7);
|
||||||
if (user.tempo_foco_total >= 600) addBadge("🧘", "Zen");
|
// 50 tasks
|
||||||
if (user.level >= 5) addBadge("⭐", "Nível 5");
|
addBadge(user.total_tasks_concluidas >= 50 ? "🎯" : "🔒", "50 Tarefas", user.total_tasks_concluidas >= 50);
|
||||||
|
// 10 hours focus (600 min)
|
||||||
|
addBadge(user.tempo_foco_total >= 600 ? "⏱️" : "🔒", "10 Horas", user.tempo_foco_total >= 600);
|
||||||
|
// 1000 XP
|
||||||
|
addBadge(user.xp >= 1000 ? "⚡" : "🔒", "1000 XP", user.xp >= 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBadge(String emoji, String name) {
|
private void addBadge(String emoji, String name, boolean unlocked) {
|
||||||
LinearLayout badge = new LinearLayout(getContext());
|
LinearLayout badge = new LinearLayout(getContext());
|
||||||
badge.setOrientation(LinearLayout.VERTICAL);
|
badge.setOrientation(LinearLayout.VERTICAL);
|
||||||
badge.setGravity(android.view.Gravity.CENTER);
|
badge.setGravity(android.view.Gravity.CENTER);
|
||||||
@@ -117,12 +123,14 @@ public class ProfileFragment extends Fragment {
|
|||||||
|
|
||||||
TextView tvEmoji = new TextView(getContext());
|
TextView tvEmoji = new TextView(getContext());
|
||||||
tvEmoji.setText(emoji);
|
tvEmoji.setText(emoji);
|
||||||
tvEmoji.setTextSize(24);
|
tvEmoji.setTextSize(32);
|
||||||
|
if (!unlocked) tvEmoji.setAlpha(0.3f);
|
||||||
|
|
||||||
TextView tvName = new TextView(getContext());
|
TextView tvName = new TextView(getContext());
|
||||||
tvName.setText(name);
|
tvName.setText(name);
|
||||||
tvName.setTextSize(8);
|
tvName.setTextSize(10);
|
||||||
tvName.setGravity(android.view.Gravity.CENTER);
|
tvName.setGravity(android.view.Gravity.CENTER);
|
||||||
|
tvName.setTextColor(getResources().getColor(unlocked ? R.color.text_primary : R.color.text_secondary));
|
||||||
|
|
||||||
badge.addView(tvEmoji);
|
badge.addView(tvEmoji);
|
||||||
badge.addView(tvName);
|
badge.addView(tvName);
|
||||||
|
|||||||
@@ -12,14 +12,13 @@ import android.widget.EditText;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import android.widget.ListView;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class SearchFragment extends Fragment {
|
public class SearchFragment extends Fragment {
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
private ListView recyclerView;
|
||||||
private EditText searchBar;
|
private EditText searchBar;
|
||||||
private ArrayAdapter<String> adapter;
|
private ArrayAdapter<String> adapter;
|
||||||
private ArrayList<String> allItems;
|
private ArrayList<String> allItems;
|
||||||
@@ -35,7 +34,6 @@ public class SearchFragment extends Fragment {
|
|||||||
allItems = new ArrayList<>(Arrays.asList("Item 1", "Item 2", "Item 3", "Another Item", "More Items"));
|
allItems = new ArrayList<>(Arrays.asList("Item 1", "Item 2", "Item 3", "Another Item", "More Items"));
|
||||||
|
|
||||||
adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, allItems);
|
adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, allItems);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
searchBar.addTextChangedListener(new TextWatcher() {
|
searchBar.addTextChangedListener(new TextWatcher() {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
@@ -36,7 +37,8 @@ public class SettingsActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
private void initSettings() {
|
private void initSettings() {
|
||||||
// --- CONTA ---
|
// --- CONTA ---
|
||||||
setupClickable(R.id.settingEmail, "Email", FirebaseAuth.getInstance().getCurrentUser().getEmail(), null);
|
setupClickable(R.id.settingEditProfile, "Editar Perfil", "Nome, Bio, Avatar", v -> showEditProfileDialog());
|
||||||
|
setupClickable(R.id.settingEmail, "Email", FirebaseAuth.getInstance().getCurrentUser().getEmail(), v -> showChangeEmailDialog());
|
||||||
setupClickable(R.id.settingPassword, "Alterar Palavra-passe", "********", v -> resetPassword());
|
setupClickable(R.id.settingPassword, "Alterar Palavra-passe", "********", v -> resetPassword());
|
||||||
setupSwitch(R.id.settingPublicProfile, "Perfil Público", "public_profile", true);
|
setupSwitch(R.id.settingPublicProfile, "Perfil Público", "public_profile", true);
|
||||||
|
|
||||||
@@ -59,7 +61,12 @@ public class SettingsActivity extends AppCompatActivity {
|
|||||||
setupClickable(R.id.settingExportData, "Exportar Dados", "JSON/CSV", null);
|
setupClickable(R.id.settingExportData, "Exportar Dados", "JSON/CSV", null);
|
||||||
|
|
||||||
findViewById(R.id.btnDeleteAccount).setOnClickListener(v -> {
|
findViewById(R.id.btnDeleteAccount).setOnClickListener(v -> {
|
||||||
Toast.makeText(this, "Funcionalidade disponível em breve", Toast.LENGTH_SHORT).show();
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle("Eliminar Conta")
|
||||||
|
.setMessage("Tens a certeza? Todos os teus dados serão apagados permanentemente.")
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.setPositiveButton("Sim, Eliminar", (dialog, which) -> deleteAccount())
|
||||||
|
.show();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +103,60 @@ public class SettingsActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showEditProfileDialog() {
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.dialog_edit_profile, null);
|
||||||
|
EditText etName = view.findViewById(R.id.etEditName);
|
||||||
|
EditText etBio = view.findViewById(R.id.etEditBio);
|
||||||
|
|
||||||
|
String uid = FirebaseAuth.getInstance().getUid();
|
||||||
|
FirestoreManager.getInstance().getUser(uid, user -> {
|
||||||
|
etName.setText(user.usuario);
|
||||||
|
etBio.setText(user.bio);
|
||||||
|
});
|
||||||
|
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle("Editar Perfil")
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton("Guardar", (dialog, which) -> {
|
||||||
|
String name = etName.getText().toString();
|
||||||
|
String bio = etBio.getText().toString();
|
||||||
|
java.util.Map<String, Object> updates = new java.util.HashMap<>();
|
||||||
|
updates.put("usuario", name);
|
||||||
|
updates.put("bio", bio);
|
||||||
|
FirestoreManager.getInstance().updateUserStats(uid, updates);
|
||||||
|
Toast.makeText(this, "Perfil atualizado!", Toast.LENGTH_SHORT).show();
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showChangeEmailDialog() {
|
||||||
|
EditText input = new EditText(this);
|
||||||
|
input.setHint("Novo email");
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle("Alterar Email")
|
||||||
|
.setView(input)
|
||||||
|
.setPositiveButton("Confirmar", (dialog, which) -> {
|
||||||
|
String newEmail = input.getText().toString();
|
||||||
|
FirebaseAuth.getInstance().getCurrentUser().updateEmail(newEmail)
|
||||||
|
.addOnSuccessListener(aVoid -> Toast.makeText(this, "Email alterado!", Toast.LENGTH_SHORT).show())
|
||||||
|
.addOnFailureListener(e -> Toast.makeText(this, "Erro: " + e.getMessage(), Toast.LENGTH_LONG).show());
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteAccount() {
|
||||||
|
String uid = FirebaseAuth.getInstance().getUid();
|
||||||
|
com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("users").document(uid).delete();
|
||||||
|
FirebaseAuth.getInstance().getCurrentUser().delete()
|
||||||
|
.addOnSuccessListener(aVoid -> {
|
||||||
|
Intent intent = new Intent(this, LoginActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void showDurationDialog(String key, String title, int current) {
|
private void showDurationDialog(String key, String title, int current) {
|
||||||
EditText input = new EditText(this);
|
EditText input = new EditText(this);
|
||||||
input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
|
input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
|
||||||
@@ -105,9 +166,20 @@ public class SettingsActivity extends AppCompatActivity {
|
|||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setView(input)
|
.setView(input)
|
||||||
.setPositiveButton("Guardar", (dialog, which) -> {
|
.setPositiveButton("Guardar", (dialog, which) -> {
|
||||||
int val = Integer.parseInt(input.getText().toString());
|
try {
|
||||||
sharedPreferences.edit().putInt(key, val).apply();
|
int val = Integer.parseInt(input.getText().toString());
|
||||||
recreate();
|
sharedPreferences.edit().putInt(key, val).apply();
|
||||||
|
|
||||||
|
// Also update in Firestore if user is logged in
|
||||||
|
String uid = FirebaseAuth.getInstance().getUid();
|
||||||
|
if (uid != null) {
|
||||||
|
java.util.Map<String, Object> updates = new java.util.HashMap<>();
|
||||||
|
if (key.equals("focus_duration")) updates.put("meta_diaria_foco", val);
|
||||||
|
FirestoreManager.getInstance().updateUserStats(uid, updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
recreate();
|
||||||
|
} catch (Exception e) {}
|
||||||
})
|
})
|
||||||
.setNegativeButton("Cancelar", null)
|
.setNegativeButton("Cancelar", null)
|
||||||
.show();
|
.show();
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import android.widget.ImageView;
|
|||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import java.util.Calendar;
|
||||||
import com.google.firebase.auth.FirebaseAuth;
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
import com.google.firebase.firestore.ListenerRegistration;
|
import com.google.firebase.firestore.ListenerRegistration;
|
||||||
|
|
||||||
@@ -191,12 +194,3 @@ public class TrophiesActivity extends AppCompatActivity {
|
|||||||
if (userListener != null) userListener.remove();
|
if (userListener != null) userListener.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (userListener != null) {
|
|
||||||
userListener.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class Usuario {
|
|||||||
public int sessoes_foco_completas = 0;
|
public int sessoes_foco_completas = 0;
|
||||||
public int dias_ativos = 1;
|
public int dias_ativos = 1;
|
||||||
public String last_active_date = ""; // YYYY-MM-DD
|
public String last_active_date = ""; // YYYY-MM-DD
|
||||||
|
public String last_reward_claim_date = ""; // YYYY-MM-DD
|
||||||
public String avatar_url = "";
|
public String avatar_url = "";
|
||||||
|
|
||||||
public Usuario() {}
|
public Usuario() {}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public class UsuariosService {
|
|||||||
};
|
};
|
||||||
for (String title : defaultTasks) {
|
for (String title : defaultTasks) {
|
||||||
String taskId = getFirestore().collection("tasks").document().getId();
|
String taskId = getFirestore().collection("tasks").document().getId();
|
||||||
Task task = new Task(taskId, title, 50, uid);
|
Task task = new Task(taskId, title, 50, 25, uid);
|
||||||
getFirestore().collection("tasks").document(taskId).set(task);
|
getFirestore().collection("tasks").document(taskId).set(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
<androidx.cardview.widget.CardView style="@style/SettingsCard">
|
<androidx.cardview.widget.CardView style="@style/SettingsCard">
|
||||||
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
|
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
|
||||||
|
<include layout="@layout/item_settings_clickable" android:id="@+id/settingEditProfile" />
|
||||||
<include layout="@layout/item_settings_clickable" android:id="@+id/settingEmail" />
|
<include layout="@layout/item_settings_clickable" android:id="@+id/settingEmail" />
|
||||||
<include layout="@layout/item_settings_clickable" android:id="@+id/settingPassword" />
|
<include layout="@layout/item_settings_clickable" android:id="@+id/settingPassword" />
|
||||||
<include layout="@layout/item_settings_switch" android:id="@+id/settingPublicProfile" />
|
<include layout="@layout/item_settings_switch" android:id="@+id/settingPublicProfile" />
|
||||||
|
|||||||
@@ -176,22 +176,42 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<!-- 3. 🎯 TAREFAS DO DIA -->
|
<Button
|
||||||
<TextView
|
android:id="@+id/btnAddTasks"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="56dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="24dp"
|
||||||
android:text="Tarefas do Dia"
|
android:background="@drawable/button_primary"
|
||||||
android:textColor="@color/text_primary"
|
android:text="+ Adicionar Tarefa"
|
||||||
android:textSize="20sp"
|
android:textAllCaps="false"
|
||||||
android:textStyle="bold" />
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:backgroundTint="@null" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/tasksContainer"
|
android:id="@+id/layoutTasksSection"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"
|
android:orientation="vertical"
|
||||||
android:orientation="vertical" />
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:text="Tarefas do Dia"
|
||||||
|
android:textColor="@color/text_primary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvTasks"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:nestedScrollingEnabled="false" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvNoTasksIncentive"
|
android:id="@+id/tvNoTasksIncentive"
|
||||||
@@ -398,19 +418,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<!-- 8. ➕ BOTÃO ADICIONAR TAREFA -->
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnAddTasks"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_marginBottom="32dp"
|
|
||||||
android:background="@drawable/button_primary"
|
|
||||||
android:text="+ Adicionar Tarefa"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:backgroundTint="@null" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Search..." />
|
android:hint="Search..." />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<ListView
|
||||||
android:id="@+id/recycler_view"
|
android:id="@+id/recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<item name="colorOnSecondary">@color/background_light</item>
|
<item name="colorOnSecondary">@color/background_light</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor">@color/background_light</item>
|
<item name="android:statusBarColor">@color/background_light</item>
|
||||||
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
|
<item name="android:windowLightStatusBar" tools:targetApi="M">false</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="android:windowBackground">@color/background_light</item>
|
<item name="android:windowBackground">@color/background_light</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<item name="nodeCircle" type="id">circle</item>
|
<item name="nodeCircle" type="id" />
|
||||||
<item name="nodeDayInitial" type="id">dayInitial</item>
|
<item name="nodeDayInitial" type="id" />
|
||||||
<item name="nodeDayLabel" type="id">nodeDayLabel</item>
|
<item name="nodeDayLabel" type="id" />
|
||||||
<item name="nodeProgress" type="id">nodeProgress</item>
|
<item name="nodeProgress" type="id" />
|
||||||
</resources>
|
</resources>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<item name="colorOnSecondary">#11181C</item>
|
<item name="colorOnSecondary">#11181C</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor">#F9FAFB</item>
|
<item name="android:statusBarColor">#F9FAFB</item>
|
||||||
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
|
<item name="android:windowLightStatusBar" tools:targetApi="M">true</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="android:windowBackground">#F9FAFB</item>
|
<item name="android:windowBackground">#F9FAFB</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
5145
build_output.txt
5145
build_output.txt
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,3 @@
|
|||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
|
||||||
android.defaults.buildfeatures.resvalues=true
|
|
||||||
android.sdk.defaultTargetSdkToCompileSdkIfUnset=false
|
|
||||||
android.enableAppCompileTimeRClass=false
|
|
||||||
android.usesSdkInManifest.disallowed=false
|
|
||||||
android.uniquePackageNames=false
|
|
||||||
android.dependency.useConstraints=true
|
android.dependency.useConstraints=true
|
||||||
android.r8.strictFullModeForKeepRules=false
|
android.r8.strictFullModeForKeepRules=false
|
||||||
android.r8.optimizedResourceShrinking=false
|
|
||||||
android.builtInKotlin=false
|
|
||||||
android.newDsl=false
|
|
||||||
|
|||||||
Reference in New Issue
Block a user