erro ao realizar a tarefa

This commit is contained in:
MeuNome
2026-04-29 10:24:56 +01:00
parent 84e4a7f8b0
commit e38e791790
26 changed files with 1641 additions and 123 deletions

View File

@@ -3,6 +3,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<application <application
android:name=".FluxupApplication" android:name=".FluxupApplication"

View File

@@ -71,8 +71,17 @@ public class FirestoreManager {
/** /**
* Atualiza o estado de uma tarefa. * Atualiza o estado de uma tarefa.
*/ */
public void updateTask(Task task, Runnable onSuccess) {
db.collection("tasks").document(task.id).set(task)
.addOnSuccessListener(aVoid -> {
android.util.Log.d("FLUXUP_DEBUG", "TASK_UPDATE_SUCCESS");
if (onSuccess != null) onSuccess.run();
})
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "TASK_UPDATE_FAIL: " + e.getMessage()));
}
public void updateTask(Task task) { public void updateTask(Task task) {
db.collection("tasks").document(task.id).set(task); updateTask(task, null);
} }
/** /**
@@ -92,19 +101,75 @@ public class FirestoreManager {
/** /**
* Atualiza campos específicos do perfil do utilizador (ex: XP, Streak). * Atualiza campos específicos do perfil do utilizador (ex: XP, Streak).
*/ */
public void updateUserStats(String uid, Map<String, Object> updates, Runnable onSuccess) {
db.collection("users").document(uid).update(updates)
.addOnSuccessListener(aVoid -> {
if (onSuccess != null) onSuccess.run();
})
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "UPDATE_USER_STATS_FAIL: " + e.getMessage()));
}
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); updateUserStats(uid, updates, null);
} }
/** /**
* Regista um log de XP. * Regista um log de XP.
*/ */
public void addXpLog(String uid, int amount, String type) { public void addXpLog(String uid, int amount, String type, String taskId) {
Map<String, Object> log = new java.util.HashMap<>(); Map<String, Object> log = new java.util.HashMap<>();
log.put("userId", uid); log.put("userId", uid);
log.put("amount", amount); log.put("amount", amount);
log.put("type", type); log.put("type", type);
if (taskId != null) log.put("taskId", taskId);
log.put("created_at", com.google.firebase.firestore.FieldValue.serverTimestamp()); log.put("created_at", com.google.firebase.firestore.FieldValue.serverTimestamp());
db.collection("xp_logs").add(log); db.collection("xp_logs").add(log)
.addOnSuccessListener(ref -> android.util.Log.d("FLUXUP_DEBUG", "XP_LOG_INSERT_SUCCESS"))
.addOnFailureListener(e -> android.util.Log.e("FLUXUP_DEBUG", "XP_LOG_INSERT_FAIL: " + e.getMessage()));
}
public void addXpLog(String uid, int amount, String type) {
addXpLog(uid, amount, type, null);
}
/**
* Calcula o XP total ganho hoje a partir dos logs.
*/
public void getTodayXp(String uid, Consumer<Integer> callback) {
if (uid == null) {
android.util.Log.e("FLUXUP_DEBUG", "getTodayXp: uid is null");
callback.accept(0);
return;
}
java.util.Calendar cal = java.util.Calendar.getInstance();
cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
java.util.Date start = cal.getTime();
cal.add(java.util.Calendar.DAY_OF_MONTH, 1);
java.util.Date end = cal.getTime();
db.collection("xp_logs")
.whereEqualTo("userId", uid)
.whereGreaterThanOrEqualTo("created_at", start)
.whereLessThan("created_at", end)
.get()
.addOnSuccessListener(snapshots -> {
int total = 0;
if (snapshots != null) {
for (com.google.firebase.firestore.QueryDocumentSnapshot doc : snapshots) {
Long amount = doc.getLong("amount");
if (amount != null) total += amount.intValue();
}
}
android.util.Log.d("FLUXUP_DEBUG", "TODAY_XP_FROM_LOGS: " + total);
callback.accept(total);
})
.addOnFailureListener(e -> {
android.util.Log.e("FLUXUP_DEBUG", "XP_QUERY_FAIL: " + e.getMessage());
callback.accept(0);
});
} }
} }

View File

@@ -1,5 +1,6 @@
package com.fluxup.app; package com.fluxup.app;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer; import android.os.CountDownTimer;
@@ -50,6 +51,7 @@ public class InicioFragment extends Fragment {
private ListenerRegistration tasksListener, userListener, rankingListener; private ListenerRegistration tasksListener, userListener, rankingListener;
private List<Task> currentTasks = new ArrayList<>(); private List<Task> currentTasks = new ArrayList<>();
private Task selectedTaskForFocus = null; private Task selectedTaskForFocus = null;
private boolean isCompletingFocus = false;
private boolean isTimerRunning = false; private boolean isTimerRunning = false;
private long timeLeftInMillis = 25 * 60 * 1000; // 25 minutos private long timeLeftInMillis = 25 * 60 * 1000; // 25 minutos
@@ -165,7 +167,6 @@ public class InicioFragment extends Fragment {
} }
currentTasks = activeTasks; currentTasks = activeTasks;
updateTasksUI(); updateTasksUI();
updateTodayCard();
}); });
} }
} }
@@ -180,9 +181,7 @@ public class InicioFragment extends Fragment {
if (tvTodayStreak != null) { if (tvTodayStreak != null) {
tvTodayStreak.setText(user.streak + " dias"); tvTodayStreak.setText(user.streak + " dias");
} }
if (tvTodayXP != null) { refreshTodayStats(user);
tvTodayXP.setText(String.valueOf(user.xp_hoje));
}
// Update Reward Button State // Update Reward Button State
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());
@@ -212,7 +211,29 @@ public class InicioFragment extends Fragment {
if (tasksAdapter != null) { if (tasksAdapter != null) {
tasksAdapter.setTasks(currentTasks); tasksAdapter.setTasks(currentTasks);
} }
updateTodayCard(); refreshTodayStats();
}
private void refreshTodayStats() {
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser == null) return;
FirestoreManager.getInstance().getUser(currentUser.getUid(), this::refreshTodayStats);
}
private void refreshTodayStats(Usuario user) {
if (user == null || !isAdded()) return;
// Update basic card info (Tasks, Progress)
updateTodayCard(user);
// Update XP specifically from logs
FirestoreManager.getInstance().getTodayXp(user.id_usuario, todayXp -> {
if (isAdded() && tvTodayXP != null) {
tvTodayXP.setText(String.valueOf(todayXp));
android.util.Log.d("FLUXUP_DEBUG", "XP_STATE_UPDATED: " + todayXp);
android.util.Log.d("FLUXUP_DEBUG", "XP_VALUE_RENDERED_IN_CARD: " + todayXp);
}
});
} }
private void selectTaskForFocus(Task task) { private void selectTaskForFocus(Task task) {
@@ -251,6 +272,8 @@ public class InicioFragment extends Fragment {
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)); updates.put("xp_semanal", com.google.firebase.firestore.FieldValue.increment(amount));
FirestoreManager.getInstance().addXpLog(uid, amount, "bonus");
FirestoreManager.getInstance().getUser(uid, user -> { FirestoreManager.getInstance().getUser(uid, user -> {
if (user != null && isAdded()) { if (user != null && isAdded()) {
int currentLevel = user.level; int currentLevel = user.level;
@@ -260,16 +283,14 @@ public class InicioFragment extends Fragment {
showLevelUpAnimation(currentLevel + 1); showLevelUpAnimation(currentLevel + 1);
} }
FirestoreManager.getInstance().updateUserStats(uid, updates); FirestoreManager.getInstance().updateUserStats(uid, updates);
refreshTodayStats();
} }
}); });
} }
} }
private void updateTodayCard() { private void updateTodayCard() {
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser(); refreshTodayStats();
if (currentUser != null) {
FirestoreManager.getInstance().getUser(currentUser.getUid(), this::updateTodayCard);
}
} }
private void updateTodayCard(Usuario user) { private void updateTodayCard(Usuario user) {
@@ -281,7 +302,7 @@ public class InicioFragment extends Fragment {
tvTodayTasksCount.setText(completed + "/" + goal); tvTodayTasksCount.setText(completed + "/" + goal);
} }
if (pbDailyTasksProgress != null) { if (pbDailyTasksProgress != null && goal > 0) {
int progress = (completed * 100) / goal; int progress = (completed * 100) / goal;
if (progress > 100) progress = 100; if (progress > 100) progress = 100;
pbDailyTasksProgress.setProgress(progress); pbDailyTasksProgress.setProgress(progress);
@@ -297,6 +318,10 @@ public class InicioFragment extends Fragment {
layoutTasksSection.setVisibility(View.VISIBLE); layoutTasksSection.setVisibility(View.VISIBLE);
} }
} }
if (tasksAdapter != null) {
tasksAdapter.setTasks(currentTasks);
}
} }
private void checkDailyResetAndStreak(Usuario user) { private void checkDailyResetAndStreak(Usuario user) {
@@ -494,13 +519,28 @@ public class InicioFragment extends Fragment {
private void triggerVibration() { private void triggerVibration() {
if (getContext() == null) return; if (getContext() == null) return;
android.os.Vibrator v = (android.os.Vibrator) getContext().getSystemService(android.content.Context.VIBRATOR_SERVICE);
if (v != null) { try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { // Check settings
v.vibrate(android.os.VibrationEffect.createOneShot(100, android.os.VibrationEffect.DEFAULT_AMPLITUDE)); android.content.SharedPreferences prefs = getContext().getSharedPreferences("FluxupSettings", android.content.Context.MODE_PRIVATE);
} else { boolean vibrationEnabled = prefs.getBoolean("vibration_on_finish", true);
v.vibrate(100);
if (!vibrationEnabled) {
android.util.Log.d("FLUXUP_DEBUG", "VIBRATION_DISABLED_BY_USER");
return;
} }
android.os.Vibrator v = (android.os.Vibrator) getContext().getSystemService(android.content.Context.VIBRATOR_SERVICE);
if (v != null && v.hasVibrator()) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
v.vibrate(android.os.VibrationEffect.createOneShot(100, android.os.VibrationEffect.DEFAULT_AMPLITUDE));
} else {
v.vibrate(100);
}
android.util.Log.d("FLUXUP_DEBUG", "VIBRATION_SUCCESS");
}
} catch (Exception e) {
android.util.Log.e("FLUXUP_DEBUG", "VIBRATION_ERROR: " + e.getMessage());
} }
} }
@@ -574,127 +614,118 @@ public class InicioFragment extends Fragment {
} }
@Override @Override
public void onFinish() { public void onFinish() {
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_FINISHED_START"); handleFocusComplete();
isTimerRunning = false; }
}.start();
isTimerRunning = true;
btnStartFocus.setText("Pausar Foco");
}
if (getActivity() != null && isAdded()) { private void handleFocusComplete() {
btnStartFocus.setText("Começar Foco"); if (isCompletingFocus) return;
} isCompletingFocus = true;
try { android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_START");
if (selectedTaskForFocus == null) {
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_FINISHED_ERROR: selectedTask is null"); try {
if (countDownTimer != null) {
countDownTimer.cancel();
android.util.Log.d("FLUXUP_DEBUG", "TIMER_CANCELLED");
}
isTimerRunning = false;
if (btnStartFocus != null) btnStartFocus.setText("Começar Foco");
if (selectedTaskForFocus == null) {
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: selectedTask null");
isCompletingFocus = false;
return;
}
android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + selectedTaskForFocus.id);
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser == null) {
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: userId null");
isCompletingFocus = false;
return;
}
String userId = currentUser.getUid();
android.util.Log.d("FLUXUP_DEBUG", "USER_ID: " + userId);
final Task task = selectedTaskForFocus;
final String taskId = task.id;
android.util.Log.d("FLUXUP_DEBUG", "TASK_UPDATE_START");
task.completed = true;
FirestoreManager.getInstance().updateTask(task, () -> {
// Task update success is logged in FirestoreManager
android.util.Log.d("FLUXUP_DEBUG", "XP_LOG_INSERT_START");
FirestoreManager.getInstance().addXpLog(userId, 50, "focus_task", taskId);
FirestoreManager.getInstance().getUser(userId, user -> {
if (!isAdded()) {
isCompletingFocus = false;
return; return;
} }
String taskId = selectedTaskForFocus.id; if (user == null) {
android.util.Log.d("FLUXUP_DEBUG", "TASK_ID: " + taskId); android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: User object null");
isCompletingFocus = false;
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; return;
} }
// Início da sincronização segura Map<String, Object> updates = new HashMap<>();
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_START"); 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(task.duration));
updates.put("tempo_foco_hoje", com.google.firebase.firestore.FieldValue.increment(task.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));
FirestoreManager.getInstance().getUser(userId, user -> { if (user.tasks_concluidas_hoje == 0) {
if (user == null) { updates.put("streak", com.google.firebase.firestore.FieldValue.increment(1));
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: User data is null"); if (user.streak + 1 > user.melhor_streak) {
return; updates.put("melhor_streak", user.streak + 1);
} }
if (!isAdded()) return; }
android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + taskId); int currentLevel = user.level;
android.util.Log.d("FLUXUP_DEBUG", "USER_ID: " + userId); int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
android.util.Log.d("FLUXUP_DEBUG", "XP_BEFORE: " + user.xp_hoje); if (user.xp + 50 >= threshold) {
updates.put("level", currentLevel + 1);
showLevelUpAnimation(currentLevel + 1);
}
// 1. Log de XP FirestoreManager.getInstance().updateUserStats(userId, updates, () -> {
Map<String, Object> log = new HashMap<>(); android.util.Log.d("FLUXUP_DEBUG", "REFRESH_HOME_START");
log.put("userId", userId); refreshTodayStats();
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") if (isAdded()) {
.add(log) android.util.Log.d("FLUXUP_DEBUG", "HOME_STATE_UPDATED");
.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(); Toast.makeText(getContext(), "Boa! Tarefa concluída +50 XP", Toast.LENGTH_LONG).show();
triggerVibration(); triggerVibration();
selectedTaskForFocus = null; selectedTaskForFocus = null;
timeLeftInMillis = 25 * 60 * 1000; timeLeftInMillis = 25 * 60 * 1000;
updateCountDownText(); updateCountDownText();
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_SUCCESS");
} }
isCompletingFocus = false;
}); });
});
});
} catch (Exception e) { } catch (Exception e) {
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_FINISHED_ERROR: " + e.getMessage()); android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: " + e.getMessage());
if (getContext() != null && isAdded()) { e.printStackTrace();
Toast.makeText(getContext(), "Erro ao concluir tarefa. Tenta novamente.", Toast.LENGTH_SHORT).show(); if (getContext() != null) {
} Toast.makeText(getContext(), "Não foi possível concluir a tarefa. Tenta novamente.", Toast.LENGTH_SHORT).show();
}
} }
}.start(); isCompletingFocus = false;
isTimerRunning = true; }
btnStartFocus.setText("Pausar Foco");
} }
private void pauseTimerWithWarning() { private void pauseTimerWithWarning() {

View File

@@ -0,0 +1,103 @@
package com.fluxup.app;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.FirebaseFirestore;
import java.util.ArrayList;
import java.util.List;
public class MyFriendsActivity extends AppCompatActivity {
private EditText etSearch;
private LinearLayout friendsContainer, emptyState;
private TextView tvFriendsCount;
private FirebaseFirestore db;
private String myUid;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_friends);
db = FirebaseFirestore.getInstance();
myUid = FirebaseAuth.getInstance().getUid();
etSearch = findViewById(R.id.etSearchFriends);
friendsContainer = findViewById(R.id.friendsListContainer);
emptyState = findViewById(R.id.emptyStateContainer);
tvFriendsCount = findViewById(R.id.tvFriendsCount);
findViewById(R.id.btnBack).setOnClickListener(v -> finish());
findViewById(R.id.btnFindNewFriends).setOnClickListener(v -> startActivity(new Intent(this, FindFriendsActivity.class)));
findViewById(R.id.btnGoToFindFriends).setOnClickListener(v -> startActivity(new Intent(this, FindFriendsActivity.class)));
loadFriends();
}
private void loadFriends() {
if (myUid == null) return;
// Fetching users I follow
db.collection("follows")
.whereEqualTo("followerId", myUid)
.get()
.addOnSuccessListener(snapshots -> {
if (snapshots.isEmpty()) {
showEmptyState(true);
return;
}
showEmptyState(false);
tvFriendsCount.setText(snapshots.size() + " Amigos");
friendsContainer.removeAllViews();
for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots.getDocuments()) {
String friendId = doc.getString("followingId");
if (friendId != null) {
fetchFriendDetails(friendId);
}
}
});
}
private void fetchFriendDetails(String friendId) {
db.collection("users").document(friendId).get().addOnSuccessListener(snapshot -> {
Usuario friend = snapshot.toObject(Usuario.class);
if (friend != null) {
addFriendItem(friend);
}
});
}
private void addFriendItem(Usuario friend) {
View view = getLayoutInflater().inflate(R.layout.item_ranking_user, friendsContainer, false);
TextView tvName = view.findViewById(R.id.tvRankingName);
TextView tvXP = view.findViewById(R.id.tvRankingXP);
TextView tvLabel = view.findViewById(R.id.tvRankingLabelTu);
tvName.setText(friend.usuario);
tvXP.setText(friend.xp + " XP");
tvLabel.setText("Nível " + friend.level);
tvLabel.setVisibility(View.VISIBLE);
tvLabel.setTextColor(getResources().getColor(R.color.primary_purple));
view.setOnClickListener(v -> {
// Open public profile (future)
Toast.makeText(this, "Perfil de " + friend.usuario, Toast.LENGTH_SHORT).show();
});
friendsContainer.addView(view);
}
private void showEmptyState(boolean show) {
emptyState.setVisibility(show ? View.VISIBLE : View.GONE);
friendsContainer.setVisibility(show ? View.GONE : View.VISIBLE);
}
}

View File

@@ -0,0 +1,52 @@
package com.fluxup.app;
import com.fluxup.app.R;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import androidx.core.app.ActivityCompat;
public class NotificationHelper {
private static final String CHANNEL_ID = "fluxup_notifications";
private static final String CHANNEL_NAME = "Fluxup Reminders";
public static void showNotification(Context context, String title, String message) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_nav_home)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent);
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
// Verificar permissão no Android 13+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
return;
}
}
notificationManagerCompat.notify((int) System.currentTimeMillis(), builder.build());
}
}

View File

@@ -55,6 +55,7 @@ public class SettingsActivity extends AppCompatActivity {
// --- FOCO --- // --- FOCO ---
setupClickable(R.id.settingFocusDuration, "Duração do Foco", sharedPreferences.getInt("focus_duration", 25) + " min", v -> showDurationDialog("focus_duration", "Duração do Foco", 25)); setupClickable(R.id.settingFocusDuration, "Duração do Foco", sharedPreferences.getInt("focus_duration", 25) + " min", v -> showDurationDialog("focus_duration", "Duração do Foco", 25));
setupClickable(R.id.settingBreakDuration, "Duração da Pausa", sharedPreferences.getInt("break_duration", 5) + " min", v -> showDurationDialog("break_duration", "Duração da Pausa", 5)); setupClickable(R.id.settingBreakDuration, "Duração da Pausa", sharedPreferences.getInt("break_duration", 5) + " min", v -> showDurationDialog("break_duration", "Duração da Pausa", 5));
setupSwitch(R.id.settingVibration, "Vibração ao Terminar", "vibration_on_finish", true);
// --- PRIVACIDADE --- // --- PRIVACIDADE ---
setupSwitch(R.id.settingIncognito, "Modo Incógnito", "incognito", false); setupSwitch(R.id.settingIncognito, "Modo Incógnito", "incognito", false);

View File

@@ -0,0 +1,120 @@
package com.fluxup.app;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
import java.util.ArrayList;
import java.util.List;
public class StatisticsActivity extends AppCompatActivity {
private LineChart xpChart;
private BarChart focusChart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_statistics);
xpChart = findViewById(R.id.xpChart);
focusChart = findViewById(R.id.focusChart);
findViewById(R.id.btnBack).setOnClickListener(v -> finish());
setupXPChart();
setupFocusChart();
loadStats();
}
private void setupXPChart() {
List<Entry> entries = new ArrayList<>();
entries.add(new Entry(0, 100));
entries.add(new Entry(1, 150));
entries.add(new Entry(2, 130));
entries.add(new Entry(3, 200));
entries.add(new Entry(4, 250));
entries.add(new Entry(5, 220));
entries.add(new Entry(6, 300));
LineDataSet dataSet = new LineDataSet(entries, "XP Diário");
dataSet.setColor(Color.parseColor("#7C3AED"));
dataSet.setCircleColor(Color.parseColor("#7C3AED"));
dataSet.setLineWidth(3f);
dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
dataSet.setDrawFilled(true);
dataSet.setFillColor(Color.parseColor("#DDD6FE"));
dataSet.setValueTextSize(10f);
LineData lineData = new LineData(dataSet);
xpChart.setData(lineData);
xpChart.getDescription().setEnabled(false);
xpChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
xpChart.getXAxis().setDrawGridLines(false);
xpChart.getAxisRight().setEnabled(false);
xpChart.animateX(1000);
xpChart.invalidate();
}
private void setupFocusChart() {
List<BarEntry> entries = new ArrayList<>();
entries.add(new BarEntry(0, 45));
entries.add(new BarEntry(1, 60));
entries.add(new BarEntry(2, 30));
entries.add(new BarEntry(3, 90));
entries.add(new BarEntry(4, 120));
entries.add(new BarEntry(5, 45));
entries.add(new BarEntry(6, 75));
BarDataSet dataSet = new BarDataSet(entries, "Minutos de Foco");
dataSet.setColor(Color.parseColor("#3B82F6"));
dataSet.setValueTextSize(10f);
BarData barData = new BarData(dataSet);
focusChart.setData(barData);
focusChart.getDescription().setEnabled(false);
focusChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
focusChart.getXAxis().setDrawGridLines(false);
focusChart.getAxisRight().setEnabled(false);
focusChart.animateY(1000);
focusChart.invalidate();
String[] days = {"Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"};
focusChart.getXAxis().setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float value) {
int index = (int) value;
if (index >= 0 && index < days.length) {
return days[index];
}
return "";
}
});
}
private void loadStats() {
updateStatCard(findViewById(R.id.statAvgFocus), "Média Foco", "62m");
updateStatCard(findViewById(R.id.statTasksPerDay), "Tarefas/Dia", "4.2");
updateStatCard(findViewById(R.id.statBestDay), "Melhor Dia", "Sex");
updateStatCard(findViewById(R.id.statTotalSessions), "Total Sessões", "28");
}
private void updateStatCard(View card, String label, String value) {
if (card == null) return;
TextView tvLabel = card.findViewById(R.id.tvStatLabel);
TextView tvValue = card.findViewById(R.id.tvStatValue);
if (tvLabel != null) tvLabel.setText(label);
if (tvValue != null) tvValue.setText(value);
}
}

View File

@@ -0,0 +1,85 @@
package com.fluxup.app;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class TasksAdapter extends RecyclerView.Adapter<TasksAdapter.TaskViewHolder> {
private List<Task> taskList;
private OnTaskClickListener listener;
public interface OnTaskClickListener {
void onTaskFocus(Task task);
void onTaskDelete(Task task);
void onTaskEdit(Task task);
}
public TasksAdapter(List<Task> taskList, OnTaskClickListener listener) {
this.taskList = taskList;
this.listener = listener;
}
public void setTasks(List<Task> tasks) {
this.taskList = tasks;
notifyDataSetChanged();
}
@NonNull
@Override
public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_task_home, parent, false);
return new TaskViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull TaskViewHolder holder, int position) {
Task task = taskList.get(position);
holder.bind(task, listener);
}
@Override
public int getItemCount() {
return taskList.size();
}
public static class TaskViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle, tvDuration;
Button btnFocus;
public TaskViewHolder(@NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.tvTaskTitle);
tvDuration = itemView.findViewById(R.id.tvTaskDuration);
btnFocus = itemView.findViewById(R.id.btnStartTaskFocus);
}
public void bind(Task task, OnTaskClickListener listener) {
tvTitle.setText(task.title);
tvDuration.setText(task.duration + " min");
if (task.completed) {
tvTitle.setPaintFlags(tvTitle.getPaintFlags() | android.graphics.Paint.STRIKE_THRU_TEXT_FLAG);
tvTitle.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.text_secondary));
btnFocus.setEnabled(false);
btnFocus.setAlpha(0.5f);
btnFocus.setText("Concluído");
} else {
tvTitle.setPaintFlags(tvTitle.getPaintFlags() & (~android.graphics.Paint.STRIKE_THRU_TEXT_FLAG));
tvTitle.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.text_primary));
btnFocus.setEnabled(true);
btnFocus.setAlpha(1.0f);
btnFocus.setText("Focar");
}
btnFocus.setOnClickListener(v -> listener.onTaskFocus(task));
itemView.setOnClickListener(v -> listener.onTaskEdit(task));
}
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<stroke
android:width="1dp"
android:color="#E2E8F0" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M7,14l5,-5 5,5z"/>
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#107C3AED" />
<stroke android:width="2dp" android:color="@color/primary_purple" />
<corners android:radius="@dimen/radius_md" />
</shape>

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_light">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/card_background"
app:elevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="64dp"
android:paddingHorizontal="16dp">
<ImageButton
android:id="@+id/btnBack"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_back"
app:tint="@color/text_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Os Meus Amigos"
android:textColor="@color/text_primary"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<EditText
android:id="@+id/etSearchFriends"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/edittext_bg"
android:hint="Pesquisar amigos..."
android:paddingHorizontal="16dp"
android:layout_marginBottom="20dp"
android:drawableStart="@drawable/ic_nav_search"
android:drawablePadding="12dp"
android:maxLines="1"
android:inputType="text"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:id="@+id/tvFriendsCount"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0 Amigos"
android:textStyle="bold"
android:textColor="@color/text_primary"/>
<TextView
android:id="@+id/btnFindNewFriends"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Encontrar Novos"
android:textColor="@color/primary_purple"
android:textStyle="bold"/>
</LinearLayout>
<LinearLayout
android:id="@+id/friendsListContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<LinearLayout
android:id="@+id/emptyStateContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="40dp"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ainda não tens amigos adicionados."
android:textAlignment="center"
android:textColor="@color/text_secondary"
android:layout_marginBottom="20dp"/>
<Button
android:id="@+id/btnGoToFindFriends"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Encontrar Amigos"
android:backgroundTint="@color/primary_purple"
android:textAllCaps="false"/>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -90,6 +90,7 @@
<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/settingFocusDuration" /> <include layout="@layout/item_settings_clickable" android:id="@+id/settingFocusDuration" />
<include layout="@layout/item_settings_clickable" android:id="@+id/settingBreakDuration" /> <include layout="@layout/item_settings_clickable" android:id="@+id/settingBreakDuration" />
<include layout="@layout/item_settings_switch" android:id="@+id/settingVibration" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/background_light">
<!-- Header -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="64dp"
android:paddingHorizontal="16dp"
android:background="@color/card_background">
<ImageButton
android:id="@+id/btnBack"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_back"
app:tint="@color/text_primary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Estatísticas"
android:textColor="@color/text_primary"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<!-- Selector -->
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/toggleGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="24dp"
app:singleSelection="true"
app:selectionRequired="true"
app:checkedButton="@+id/btnWeek">
<Button
android:id="@+id/btnWeek"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Semana" />
<Button
android:id="@+id/btnMonth"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mês" />
</com.google.android.material.button.MaterialButtonToggleGroup>
<!-- XP Progress Chart -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Progresso de XP"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginBottom="12dp"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_marginBottom="24dp"
app:cardCornerRadius="16dp"
app:cardElevation="1dp">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/xpChart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp" />
</androidx.cardview.widget.CardView>
<!-- Focus Time Chart -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tempo de Foco (min)"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginBottom="12dp"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_marginBottom="24dp"
app:cardCornerRadius="16dp"
app:cardElevation="1dp">
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/focusChart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp" />
</androidx.cardview.widget.CardView>
<!-- Performance Grid -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Desempenho"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginBottom="12dp"/>
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="2"
android:layout_marginBottom="40dp">
<include layout="@layout/item_stat_card" android:id="@+id/statAvgFocus" />
<include layout="@layout/item_stat_card" android:id="@+id/statTasksPerDay" />
<include layout="@layout/item_stat_card" android:id="@+id/statBestDay" />
<include layout="@layout/item_stat_card" android:id="@+id/statTotalSessions" />
</GridLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nome da Tarefa"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etTaskTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Duração (minutos)"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etTaskDuration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="25" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:layout_marginBottom="4dp"/>
<EditText
android:id="@+id/etEditName"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/edittext_bg"
android:hint="O teu nome"
android:paddingHorizontal="12dp"
android:layout_marginBottom="16dp"
android:inputType="textPersonName"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bio"
android:textColor="@color/text_secondary"
android:textSize="12sp"
android:layout_marginBottom="4dp"/>
<EditText
android:id="@+id/etEditBio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="80dp"
android:background="@drawable/edittext_bg"
android:hint="Uma frase sobre ti"
android:padding="12dp"
android:gravity="top"
android:inputType="textMultiLine"/>
</LinearLayout>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="32dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="🔥"
android:textSize="64sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="NOVO NÍVEL!"
android:textColor="@color/primary_purple"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvNewLevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5"
android:textColor="@color/text_primary"
android:textSize="48sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Estás a tornar-te uma lenda da produtividade!"
android:textColor="@color/text_secondary"
android:textSize="14sp" />
</LinearLayout>

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="12dp">
<androidx.cardview.widget.CardView
android:layout_width="50dp"
android:layout_height="50dp"
app:cardCornerRadius="25dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/ivFriendAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/ic_nav_profile" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvFriendName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome do Amigo"
android:textColor="@color/text_primary"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvFriendStats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nível 12 • 450 XP"
android:textColor="@color/text_secondary"
android:textSize="12sp" />
</LinearLayout>
<Button
android:id="@+id/btnFriendAction"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Adicionar"
android:textColor="@color/primary_purple"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardRankingUser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="12dp">
<TextView
android:id="@+id/tvRankPosition"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:text="#1"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:textSize="14sp" />
<androidx.cardview.widget.CardView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
app:cardCornerRadius="20dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/ivRankingAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/ic_nav_profile" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="12dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvRankingName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome do Utilizador"
android:textColor="@color/text_primary"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvRankingLabelTu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tu"
android:textColor="@color/primary_purple"
android:textSize="10sp"
android:textStyle="bold"
android:visibility="gone" />
</LinearLayout>
<TextView
android:id="@+id/tvRankingXP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1250 XP"
android:textColor="@color/primary_purple"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/ivRankingTrend"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="8dp"
android:src="@drawable/ic_trend_up"
app:tint="@color/success_green" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tvSettingTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Configuração"
android:textColor="@color/text_primary"
android:textSize="16sp" />
<TextView
android:id="@+id/tvSettingValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/ivChevron"
android:layout_marginEnd="8dp"
android:text="Valor"
android:textColor="@color/text_secondary"
android:textSize="14sp" />
<ImageView
android:id="@+id/ivChevron"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_back"
android:rotation="180"
android:alpha="0.3" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@color/border_color"
android:layout_marginStart="16dp" />
</RelativeLayout>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="64dp"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tvSettingTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Configuração"
android:textColor="@color/text_primary"
android:textSize="16sp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchSetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
app:useMaterialThemeColors="true" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@color/border_color"
android:layout_marginStart="16dp" />
</RelativeLayout>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_columnWeight="1"
android:layout_margin="6dp"
app:cardCornerRadius="16dp"
app:cardElevation="1dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvStatLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Média Foco"
android:textColor="@color/text_secondary"
android:textSize="12sp" />
<TextView
android:id="@+id/tvStatValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="45m"
android:textColor="@color/primary_purple"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginTop="4dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_columnWeight="1"
app:cardCornerRadius="12dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="12dp">
<TextView
android:id="@+id/tvStatIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="⚡"
android:textSize="20sp"
android:layout_marginBottom="4dp"/>
<TextView
android:id="@+id/tvStatValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@color/text_primary"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvStatLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="XP"
android:textColor="@color/text_secondary"
android:textSize="10sp" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
app:cardCornerRadius="@dimen/radius_md"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvTaskTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome da Tarefa"
android:textColor="@color/text_primary"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvTaskDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25 min"
android:textColor="@color/text_secondary"
android:textSize="14sp" />
</LinearLayout>
<Button
android:id="@+id/btnStartTaskFocus"
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Focar"
android:textColor="@color/white"
android:backgroundTint="@color/primary_purple"
android:textSize="12sp"
app:cornerRadius="20dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>

287
build_stacktrace.txt Normal file
View File

@@ -0,0 +1,287 @@
WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by net.rubygrapefruit.platform.internal.NativeLibraryLoader in an unnamed module (file:/Users/230407/.gradle/wrapper/dists/gradle-9.3.1-bin/23ovyewtku6u96viwx3xl3oks/gradle-9.3.1/lib/native-platform-0.22-milestone-29.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
> Configure project :app
WARNING: The option setting 'android.usesSdkInManifest.disallowed=false' is deprecated.
The current default is 'true'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.sdk.defaultTargetSdkToCompileSdkIfUnset=false' is deprecated.
The current default is 'true'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.enableAppCompileTimeRClass=false' is deprecated.
The current default is 'true'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.builtInKotlin=false' is deprecated.
The current default is 'true'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.newDsl=false' is deprecated.
The current default is 'true'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.r8.optimizedResourceShrinking=false' is deprecated.
The current default is 'true'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.defaults.buildfeatures.resvalues=true' is deprecated.
The current default is 'false'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The option setting 'android.enableJetifier=true' is deprecated.
The current default is 'false'.
It will be removed in version 10.0 of the Android Gradle plugin.
WARNING: The property android.dependency.excludeLibraryComponentsFromConstraints improves project import performance for very large projects. It should be enabled to improve performance.
To suppress this warning, add android.generateSyncIssueWhenLibraryConstraintsAreEnabled=false to gradle.properties
WARNING: The property android.dependency.excludeLibraryComponentsFromConstraints improves project import performance for very large projects. It should be enabled to improve performance.
To suppress this warning, add android.generateSyncIssueWhenLibraryConstraintsAreEnabled=false to gradle.properties
WARNING: The property android.dependency.excludeLibraryComponentsFromConstraints improves project import performance for very large projects. It should be enabled to improve performance.
To suppress this warning, add android.generateSyncIssueWhenLibraryConstraintsAreEnabled=false to gradle.properties
WARNING: The property android.dependency.excludeLibraryComponentsFromConstraints improves project import performance for very large projects. It should be enabled to improve performance.
To suppress this warning, add android.generateSyncIssueWhenLibraryConstraintsAreEnabled=false to gradle.properties
> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:mergeDebugNativeDebugMetadata NO-SOURCE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:checkDebugAarMetadata UP-TO-DATE
> Task :app:generateDebugResValues UP-TO-DATE
> Task :app:processDebugGoogleServices UP-TO-DATE
> Task :app:mapDebugSourceSetPaths UP-TO-DATE
> Task :app:processDebugNavigationResources UP-TO-DATE
> Task :app:compileDebugNavigationResources UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:packageDebugResources UP-TO-DATE
> Task :app:parseDebugLocalResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugMainManifest UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugManifestForPackage UP-TO-DATE
> Task :app:generateDebugAssets UP-TO-DATE
> Task :app:mergeDebugAssets UP-TO-DATE
> Task :app:compressDebugAssets UP-TO-DATE
> Task :app:processDebugJavaRes NO-SOURCE
> Task :app:mergeDebugJavaResource UP-TO-DATE
> Task :app:desugarDebugFileDependencies
> Task :app:mergeDebugJniLibFolders
> Task :app:mergeDebugNativeLibs NO-SOURCE
> Task :app:stripDebugDebugSymbols NO-SOURCE
> Task :app:mergeDebugResources FAILED
/Users/230407/Desktop/FluxupP/app/src/main/res/values/ids.xml:3:4: <item> inner element must either be a resource reference or empty.
/Users/230407/Desktop/FluxupP/app/src/main/res/values/ids.xml:4:4: <item> inner element must either be a resource reference or empty.
/Users/230407/Desktop/FluxupP/app/src/main/res/values/ids.xml:5:4: <item> inner element must either be a resource reference or empty.
/Users/230407/.gradle/caches/9.3.1/transforms/3090efbf6d47378a0528b3ce679aa974/transformed/transition-1.4.1/res/values/values.xml:4:4: <item> inner element must either be a resource reference or empty.
> Task :app:checkDebugDuplicateClasses
> Task :app:validateSigningDebug
[Incubating] Problems report is available at: file:///Users/230407/Desktop/FluxupP/build/reports/problems/problems-report.html
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:mergeDebugResources'.
> A failure occurred while executing com.android.build.gradle.internal.res.ResourceCompilerRunnable
> Resource compilation failed (Failed to compile values resource file /Users/230407/Desktop/FluxupP/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml. Cause: java.lang.IllegalStateException: Can not extract resource from com.android.aaptcompiler.ParsedResource@247bbe22.,Can not extract resource from com.android.aaptcompiler.ParsedResource@255775e2.,Can not extract resource from com.android.aaptcompiler.ParsedResource@87786c9.,Can not extract resource from com.android.aaptcompiler.ParsedResource@460c8a21.). Check logs for more details.
* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights from a Build Scan (powered by Develocity).
> Get more help at https://help.gradle.org.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:135)
at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:288)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:133)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:121)
at org.gradle.api.internal.tasks.execution.ProblemsTaskPathTrackingTaskExecuter.execute(ProblemsTaskPathTrackingTaskExecuter.java:41)
at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
at org.gradle.execution.plan.DefaultNodeExecutor.executeLocalTaskNode(DefaultNodeExecutor.java:55)
at org.gradle.execution.plan.DefaultNodeExecutor.execute(DefaultNodeExecutor.java:34)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:339)
at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:84)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:339)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:328)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:459)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:376)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
Caused by: org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing com.android.build.gradle.internal.res.ResourceCompilerRunnable
at org.gradle.workers.internal.DefaultWorkerExecutor$WorkItemExecution.waitForCompletion(DefaultWorkerExecutor.java:289)
at org.gradle.internal.work.DefaultAsyncWorkTracker.lambda$waitForItemsAndGatherFailures$2(DefaultAsyncWorkTracker.java:130)
at org.gradle.internal.Factories$1.create(Factories.java:30)
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withoutLocks$2(DefaultWorkerLeaseService.java:344)
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
at org.gradle.internal.work.DefaultWorkerLeaseService.withoutLocks(DefaultWorkerLeaseService.java:342)
at org.gradle.internal.work.DefaultWorkerLeaseService.withoutLocks(DefaultWorkerLeaseService.java:326)
at org.gradle.internal.work.DefaultWorkerLeaseService.withoutLock(DefaultWorkerLeaseService.java:331)
at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForItemsAndGatherFailures(DefaultAsyncWorkTracker.java:126)
at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForItemsAndGatherFailures(DefaultAsyncWorkTracker.java:92)
at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForAll(DefaultAsyncWorkTracker.java:78)
at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForCompletion(DefaultAsyncWorkTracker.java:66)
at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:267)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:244)
at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:227)
at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:210)
at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:176)
at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:110)
at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:47)
at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:64)
at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:61)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:61)
at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:47)
at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:42)
at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:75)
at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:51)
at org.gradle.internal.execution.steps.PreCreateOutputParentsStep.execute(PreCreateOutputParentsStep.java:29)
at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.executeMutable(RemovePreviousOutputsStep.java:70)
at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.executeMutable(RemovePreviousOutputsStep.java:40)
at org.gradle.internal.execution.steps.MutableStep.execute(MutableStep.java:25)
at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:62)
at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:27)
at org.gradle.internal.execution.steps.CaptureOutputsAfterExecutionStep.execute(CaptureOutputsAfterExecutionStep.java:69)
at org.gradle.internal.execution.steps.CaptureOutputsAfterExecutionStep.execute(CaptureOutputsAfterExecutionStep.java:46)
at org.gradle.internal.execution.steps.ResolveInputChangesStep.executeMutable(ResolveInputChangesStep.java:39)
at org.gradle.internal.execution.steps.ResolveInputChangesStep.executeMutable(ResolveInputChangesStep.java:28)
at org.gradle.internal.execution.steps.MutableStep.execute(MutableStep.java:25)
at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:192)
at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:76)
at org.gradle.internal.Either$Right.fold(Either.java:176)
at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:62)
at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:74)
at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:49)
at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:46)
at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:35)
at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:75)
at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:53)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:53)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:35)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
at org.gradle.internal.execution.steps.ResolveIncrementalCachingStateStep.executeDelegate(ResolveIncrementalCachingStateStep.java:49)
at org.gradle.internal.execution.steps.ResolveIncrementalCachingStateStep.executeDelegate(ResolveIncrementalCachingStateStep.java:27)
at org.gradle.internal.execution.steps.AbstractResolveCachingStateStep.execute(AbstractResolveCachingStateStep.java:71)
at org.gradle.internal.execution.steps.AbstractResolveCachingStateStep.execute(AbstractResolveCachingStateStep.java:39)
at org.gradle.internal.execution.steps.ResolveChangesStep.executeMutable(ResolveChangesStep.java:63)
at org.gradle.internal.execution.steps.ResolveChangesStep.executeMutable(ResolveChangesStep.java:34)
at org.gradle.internal.execution.steps.MutableStep.execute(MutableStep.java:25)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:64)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:42)
at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:77)
at org.gradle.internal.execution.steps.AbstractCaptureStateBeforeExecutionStep.execute(AbstractCaptureStateBeforeExecutionStep.java:46)
at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.executeWithNonEmptySources(AbstractSkipEmptyWorkStep.java:133)
at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:59)
at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:36)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36)
at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23)
at org.gradle.internal.execution.steps.HandleStaleOutputsStep.executeMutable(HandleStaleOutputsStep.java:77)
at org.gradle.internal.execution.steps.HandleStaleOutputsStep.executeMutable(HandleStaleOutputsStep.java:43)
at org.gradle.internal.execution.steps.MutableStep.execute(MutableStep.java:25)
at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35)
at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:305)
at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31)
at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22)
at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40)
at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23)
at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67)
at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67)
at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39)
at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46)
at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34)
at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:44)
at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:31)
at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:68)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:132)
... 30 more
Caused by: com.android.aaptcompiler.ResourceCompilationException: Resource compilation failed (Failed to compile values resource file /Users/230407/Desktop/FluxupP/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml. Cause: java.lang.IllegalStateException: Can not extract resource from com.android.aaptcompiler.ParsedResource@247bbe22.,Can not extract resource from com.android.aaptcompiler.ParsedResource@255775e2.,Can not extract resource from com.android.aaptcompiler.ParsedResource@87786c9.,Can not extract resource from com.android.aaptcompiler.ParsedResource@460c8a21.). Check logs for more details.
at com.android.aaptcompiler.ResourceCompiler.compileResource(ResourceCompiler.kt:120)
at com.android.build.gradle.internal.res.ResourceCompilerRunnable$Companion.compileSingleResource(ResourceCompilerRunnable.kt:33)
at com.android.build.gradle.internal.res.ResourceCompilerRunnable.run(ResourceCompilerRunnable.kt:13)
at com.android.build.gradle.internal.profile.ProfileAwareWorkAction.execute(ProfileAwareWorkAction.kt:66)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:68)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:64)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:61)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:102)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:61)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:58)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:176)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169)
at org.gradle.internal.Factories$1.create(Factories.java:30)
at org.gradle.internal.work.DefaultWorkerLeaseService.lambda$withLocksAcquired$0(DefaultWorkerLeaseService.java:269)
at org.gradle.internal.work.ResourceLockStatistics$1.measure(ResourceLockStatistics.java:42)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocksAcquired(DefaultWorkerLeaseService.java:267)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:259)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133)
... 2 more
Caused by: com.android.aaptcompiler.ResourceCompilationException: Failed to compile values resource file /Users/230407/Desktop/FluxupP/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml
at com.android.aaptcompiler.ResourceCompiler.compileTable(ResourceCompiler.kt:179)
at com.android.aaptcompiler.ResourceCompiler.access$compileTable(ResourceCompiler.kt:1)
at com.android.aaptcompiler.ResourceCompiler$getCompileMethod$1.invoke(ResourceCompiler.kt:130)
at com.android.aaptcompiler.ResourceCompiler$getCompileMethod$1.invoke(ResourceCompiler.kt:130)
at com.android.aaptcompiler.ResourceCompiler.compileResource(ResourceCompiler.kt:116)
... 34 more
Caused by: java.lang.IllegalStateException: Can not extract resource from com.android.aaptcompiler.ParsedResource@247bbe22.,Can not extract resource from com.android.aaptcompiler.ParsedResource@255775e2.,Can not extract resource from com.android.aaptcompiler.ParsedResource@87786c9.,Can not extract resource from com.android.aaptcompiler.ParsedResource@460c8a21.
at com.android.aaptcompiler.TableExtractor.extractResourceValues(TableExtractor.kt:248)
at com.android.aaptcompiler.TableExtractor.extract(TableExtractor.kt:162)
at com.android.aaptcompiler.ResourceCompiler.compileTable(ResourceCompiler.kt:175)
... 38 more
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/9.3.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD FAILED in 935ms
24 actionable tasks: 5 executed, 19 up-to-date