diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml
index d469d46..5dc2fb2 100644
--- a/.idea/caches/deviceStreaming.xml
+++ b/.idea/caches/deviceStreaming.xml
@@ -1754,6 +1754,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/fluxup/app/AvatarView.java b/app/src/main/java/com/fluxup/app/AvatarView.java
index 9236194..4df71b1 100644
--- a/app/src/main/java/com/fluxup/app/AvatarView.java
+++ b/app/src/main/java/com/fluxup/app/AvatarView.java
@@ -319,16 +319,16 @@ public class AvatarView extends View {
paint.setColor(Color.parseColor("#F59E0B")); // Ouro
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
paint.setStyle(Paint.Style.FILL);
- } else if ("Platina".equalsIgnoreCase(league) || "Platinum".equalsIgnoreCase(league)) {
+ } else if ("Esmeralda".equalsIgnoreCase(league) || "Platina".equalsIgnoreCase(league) || "Platinum".equalsIgnoreCase(league)) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(Math.min(w, h) * 0.06f);
- paint.setColor(Color.parseColor("#06B6D4")); // Platina Ciano
+ paint.setColor(Color.parseColor("#4CAF50")); // Esmeralda Verde
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
paint.setStyle(Paint.Style.FILL);
} else if ("Diamante".equalsIgnoreCase(league) || "Diamond".equalsIgnoreCase(league)) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(Math.min(w, h) * 0.06f);
- paint.setColor(Color.parseColor("#6366F1")); // Diamante Indigo/Violeta
+ paint.setColor(Color.parseColor("#1E88E5")); // Diamante Azul
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
paint.setStyle(Paint.Style.FILL);
}
diff --git a/app/src/main/java/com/fluxup/app/InicioFragment.java b/app/src/main/java/com/fluxup/app/InicioFragment.java
index 5d22a64..317a1be 100644
--- a/app/src/main/java/com/fluxup/app/InicioFragment.java
+++ b/app/src/main/java/com/fluxup/app/InicioFragment.java
@@ -59,6 +59,7 @@ public class InicioFragment extends Fragment {
private TextView tvFocusPauseCount, tvFocusPenaltyWarning, tvFocusXpReward;
private int pauseCount = 0;
private boolean isCompletingFocus = false;
+ private Usuario localUser = null;
private boolean isTimerRunning = false;
private long timeLeftInMillis = 25 * 60 * 1000; // 25 minutos
@@ -196,6 +197,7 @@ public class InicioFragment extends Fragment {
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser != null) {
userListener = FirestoreManager.getInstance().observeUser(currentUser.getUid(), user -> {
+ localUser = user;
if (tvGreeting != null) {
tvGreeting.setText("Olá, " + user.usuario + "!");
}
@@ -1057,7 +1059,8 @@ public class InicioFragment extends Fragment {
final Task task = selectedTaskForFocus;
final String taskId = task.id;
- final int finalXp = calculateFocusXp();
+ final boolean taskHasBoost = task.hasBoost;
+ final int finalXp = taskHasBoost ? calculateFocusXp() * 2 : calculateFocusXp();
android.util.Log.d("FLUXUP_DEBUG", "TASK_UPDATE_START");
task.completed = true;
@@ -1101,7 +1104,11 @@ public class InicioFragment extends Fragment {
if (isAdded()) {
refreshHomeStats();
- Toast.makeText(getContext(), "Boa! Tarefa concluída +" + finalXp + " XP", Toast.LENGTH_LONG).show();
+ if (taskHasBoost) {
+ Toast.makeText(getContext(), "🚀 Boost aplicado! XP dobrado. +" + finalXp + " XP", Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(getContext(), "Boa! Tarefa concluída +" + finalXp + " XP", Toast.LENGTH_LONG).show();
+ }
triggerVibration();
selectedTaskForFocus = null;
@@ -1174,6 +1181,39 @@ public class InicioFragment extends Fragment {
android.widget.EditText etTitle = dialogView.findViewById(R.id.etTaskTitle);
android.widget.EditText etDuration = dialogView.findViewById(R.id.etTaskDuration);
+ // Boost UI
+ View cardUseBoost = dialogView.findViewById(R.id.cardUseBoost);
+ android.widget.ImageView ivBoostIcon = dialogView.findViewById(R.id.ivBoostRocketIcon);
+ android.widget.TextView tvBoostLabel = dialogView.findViewById(R.id.tvBoostLabel);
+ android.widget.TextView tvBoostCount = dialogView.findViewById(R.id.tvBoostCount);
+ final boolean[] boostActive = {false};
+
+ int boostQty = (localUser != null && localUser.inventory != null && localUser.inventory.containsKey("boost_xp"))
+ ? localUser.inventory.get("boost_xp") : 0;
+
+ if (boostQty > 0 && cardUseBoost != null) {
+ tvBoostCount.setText("x" + boostQty);
+ cardUseBoost.setVisibility(View.VISIBLE);
+ cardUseBoost.setOnClickListener(v -> {
+ boostActive[0] = !boostActive[0];
+ if (boostActive[0]) {
+ // Active state: purple highlight
+ cardUseBoost.setBackground(ContextCompat.getDrawable(getContext(), R.drawable.boost_selected_bg));
+ tvBoostLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.primary_purple));
+ tvBoostCount.setTextColor(ContextCompat.getColor(getContext(), R.color.primary_purple));
+ ivBoostIcon.setImageTintList(android.content.res.ColorStateList.valueOf(
+ ContextCompat.getColor(getContext(), R.color.primary_purple)));
+ } else {
+ // Inactive state: default gray
+ cardUseBoost.setBackground(ContextCompat.getDrawable(getContext(), R.drawable.boost_default_bg));
+ tvBoostLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary));
+ tvBoostCount.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary));
+ ivBoostIcon.setImageTintList(android.content.res.ColorStateList.valueOf(
+ ContextCompat.getColor(getContext(), R.color.text_secondary)));
+ }
+ });
+ }
+
androidx.appcompat.app.AlertDialog dialog = new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
.setTitle("Nova Tarefa")
.setView(dialogView)
@@ -1198,15 +1238,15 @@ public class InicioFragment extends Fragment {
return;
}
}
- saveNewTask(title, duration);
+ saveNewTask(title, duration, boostActive[0]);
dialog.dismiss();
});
});
dialog.show();
}
- private void saveNewTask(String title, int duration) {
- android.util.Log.d("FLUXUP_DEBUG", "Criando tarefa: " + title);
+ private void saveNewTask(String title, int duration, boolean useBoost) {
+ android.util.Log.d("FLUXUP_DEBUG", "Criando tarefa: " + title + " | boost: " + useBoost);
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser == null) {
android.util.Log.d("FLUXUP_DEBUG", "Erro ao salvar: Usuário nulo");
@@ -1215,10 +1255,19 @@ public class InicioFragment extends Fragment {
String uid = currentUser.getUid();
String taskId = com.google.firebase.firestore.FirebaseFirestore.getInstance().collection("tasks").document().getId();
Task task = new Task(taskId, title, 30, duration, uid);
-
+ task.hasBoost = useBoost;
+
FirestoreManager.getInstance().addTask(task);
android.util.Log.d("FLUXUP_DEBUG", "Tarefa salva: " + taskId);
-
+
+ // Decrement boost inventory if boost was applied
+ if (useBoost && uid != null) {
+ Map inventoryUpdate = new HashMap<>();
+ inventoryUpdate.put("inventory.boost_xp", com.google.firebase.firestore.FieldValue.increment(-1));
+ FirestoreManager.getInstance().updateUserStats(uid, inventoryUpdate);
+ android.util.Log.d("FLUXUP_DEBUG", "BOOST_CONSUMED: 1 boost_xp removed from inventory");
+ }
+
// Refresh local stats
refreshHomeStats();
}
diff --git a/app/src/main/java/com/fluxup/app/LeagueHelper.java b/app/src/main/java/com/fluxup/app/LeagueHelper.java
index 6ee0bef..19a6dfe 100644
--- a/app/src/main/java/com/fluxup/app/LeagueHelper.java
+++ b/app/src/main/java/com/fluxup/app/LeagueHelper.java
@@ -26,10 +26,8 @@ public class LeagueHelper {
new LeagueInfo("Bronze", 0, 499, R.drawable.ic_trophy_bronze, "#8D6E63", "Estás a começar a tua jornada!"),
new LeagueInfo("Prata", 500, 1499, R.drawable.ic_trophy_silver, "#B0BEC5", "A consistência está a dar frutos."),
new LeagueInfo("Ouro", 1500, 2999, R.drawable.ic_trophy_gold, "#FFD54F", "Um verdadeiro guerreiro do foco!"),
- new LeagueInfo("Platina", 3000, 4999, R.drawable.ic_trophy_platinum, "#4FC3F7", "Elite da produtividade."),
- new LeagueInfo("Diamante", 5000, 7499, R.drawable.ic_trophy_diamond, "#1E88E5", "Inquebrável e imparável."),
- new LeagueInfo("Mestre", 7500, 9999, R.drawable.ic_trophy_master, "#7C3AED", "Mestre absoluto da Fluxup."),
- new LeagueInfo("Lenda", 10000, Integer.MAX_VALUE, R.drawable.ic_trophy_legend, "#D81B60", "Uma lenda viva da disciplina!")
+ new LeagueInfo("Esmeralda", 3000, 4999, R.drawable.ic_trophy_emerald, "#4CAF50", "Elite da produtividade."),
+ new LeagueInfo("Diamante", 5000, Integer.MAX_VALUE, R.drawable.ic_trophy_diamond, "#1E88E5", "Inquebrável e imparável.")
};
public static LeagueInfo getCurrentLeague(int totalXp) {
diff --git a/app/src/main/java/com/fluxup/app/RewardsFragment.java b/app/src/main/java/com/fluxup/app/RewardsFragment.java
index 730553e..402bc80 100644
--- a/app/src/main/java/com/fluxup/app/RewardsFragment.java
+++ b/app/src/main/java/com/fluxup/app/RewardsFragment.java
@@ -664,7 +664,7 @@ public class RewardsFragment extends Fragment {
llStoreContainer.removeAllViews();
addStoreItem("mystery_box", "Caixa Misteriosa", "Ganha XP e moedas surpresa!", 60, "📦", user);
- addStoreItem("boost_xp", "Boost de XP", "Dobra o XP ganho (em breve)", 50, "🚀", user);
+ addStoreItem("boost_xp", "Boost de XP", "Dobra o XP ganho na próxima tarefa", 50, "🚀", user);
addStoreItem("streak_protect", "Proteção de Streak", "Salva a tua ofensiva se falhares um dia", 80, "🛡️", user);
addStoreItem("frame_avatar", "Moldura Épica", "Destaca o teu avatar no ranking", 100, "🖼️", user);
}
diff --git a/app/src/main/java/com/fluxup/app/Task.java b/app/src/main/java/com/fluxup/app/Task.java
index 8620e48..3738381 100644
--- a/app/src/main/java/com/fluxup/app/Task.java
+++ b/app/src/main/java/com/fluxup/app/Task.java
@@ -8,6 +8,7 @@ public class Task {
public int duration; // em minutos
public String userId;
public Long completedDate;
+ public boolean hasBoost = false;
public Task() {}
diff --git a/app/src/main/java/com/fluxup/app/TrophiesActivity.java b/app/src/main/java/com/fluxup/app/TrophiesActivity.java
index 5dabce0..c397b05 100644
--- a/app/src/main/java/com/fluxup/app/TrophiesActivity.java
+++ b/app/src/main/java/com/fluxup/app/TrophiesActivity.java
@@ -134,7 +134,7 @@ public class TrophiesActivity extends AppCompatActivity {
tvHeaderXP.setText(user.xp + " / " + next.minXp + " XP");
} else {
pbHeaderProgress.setProgress(100);
- tvHeaderXP.setText(user.xp + " XP (Lenda)");
+ tvHeaderXP.setText(user.xp + " XP (" + current.name + ")");
}
// Bottom Card
@@ -319,6 +319,8 @@ public class TrophiesActivity extends AppCompatActivity {
TextView tvTu = view.findViewById(R.id.tvRankingLabelTu);
androidx.cardview.widget.CardView card = view.findViewById(R.id.cardRankingUser);
AvatarView ivAvatar = view.findViewById(R.id.ivRankingAvatar);
+ TextView tvStreak = view.findViewById(R.id.tvRankingStreak);
+ ImageView ivTrophy = view.findViewById(R.id.ivRankingTrophy);
tvPos.setText("#" + pos);
tvName.setText(user.usuario);
@@ -328,6 +330,16 @@ public class TrophiesActivity extends AppCompatActivity {
ivAvatar.setLeague(user.league);
}
+ if (tvStreak != null) {
+ tvStreak.setText("🔥 " + user.streak);
+ }
+
+ if (ivTrophy != null) {
+ LeagueHelper.LeagueInfo userLeague = LeagueHelper.getCurrentLeague(user.xp);
+ ivTrophy.setImageResource(userLeague.iconRes);
+ ivTrophy.setVisibility(View.VISIBLE);
+ }
+
if (user.id_usuario.equals(myUid)) {
tvTu.setVisibility(View.VISIBLE);
card.setCardBackgroundColor(Color.parseColor("#F3E5F5"));
diff --git a/app/src/main/res/drawable/boost_default_bg.xml b/app/src/main/res/drawable/boost_default_bg.xml
new file mode 100644
index 0000000..b5ad3be
--- /dev/null
+++ b/app/src/main/res/drawable/boost_default_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/boost_selected_bg.xml b/app/src/main/res/drawable/boost_selected_bg.xml
new file mode 100644
index 0000000..92529d3
--- /dev/null
+++ b/app/src/main/res/drawable/boost_selected_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_rocket.xml b/app/src/main/res/drawable/ic_rocket.xml
new file mode 100644
index 0000000..552909f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_rocket.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_trophy_emerald.xml b/app/src/main/res/drawable/ic_trophy_emerald.xml
new file mode 100644
index 0000000..6293925
--- /dev/null
+++ b/app/src/main/res/drawable/ic_trophy_emerald.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/dialog_add_task.xml b/app/src/main/res/layout/dialog_add_task.xml
index 789be7b..1e89ff1 100644
--- a/app/src/main/res/layout/dialog_add_task.xml
+++ b/app/src/main/res/layout/dialog_add_task.xml
@@ -1,5 +1,6 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_ranking_user.xml b/app/src/main/res/layout/item_ranking_user.xml
index 057e572..ff99719 100644
--- a/app/src/main/res/layout/item_ranking_user.xml
+++ b/app/src/main/res/layout/item_ranking_user.xml
@@ -88,6 +88,14 @@
android:textSize="14sp"
android:textStyle="bold" />
+
+