Atualizado

This commit is contained in:
2026-03-18 10:40:21 +00:00
parent e8f64562d8
commit e6d015be65
13 changed files with 1049 additions and 623 deletions

View File

@@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-03-10T15:47:42.816610Z">
<DropdownSelection timestamp="2026-03-18T10:38:49.186279Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230410/.android/avd/Pixel_9_Pro.avd" />
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230410/.android/avd/Medium_Phone.avd" />
</handle>
</Target>
</DropdownSelection>

View File

@@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -65,6 +66,12 @@
android:enabled="true"
android:exported="false"
android:foregroundServiceType="mediaPlayback" />
<service
android:name=".GuardianNotificationService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="dataSync" />
</application>
</manifest>

View File

@@ -23,6 +23,7 @@ public class AlarmReceiver extends BroadcastReceiver {
String message = intent.getStringExtra("alarm_message");
String ringtoneUriString = intent.getStringExtra("ringtone_uri");
int alarmId = intent.getIntExtra("alarm_id", -1);
String docId = intent.getStringExtra("alarm_doc_id");
if (title == null) {
title = "Alarme de Medicamento";
@@ -39,6 +40,7 @@ public class AlarmReceiver extends BroadcastReceiver {
activityIntent.putExtra("alarm_time", new java.text.SimpleDateFormat("HH:mm", java.util.Locale.getDefault()).format(new java.util.Date()));
activityIntent.putExtra("ringtone_uri", ringtoneUriString);
activityIntent.putExtra("alarm_id", alarmId);
activityIntent.putExtra("alarm_doc_id", docId);
context.startActivity(activityIntent);
Intent serviceIntent = new Intent(context, AlarmSoundService.class);
@@ -52,7 +54,7 @@ public class AlarmReceiver extends BroadcastReceiver {
}
createNotificationChannel(context);
showNotification(context, title, message, ringtoneUriString, alarmId);
showNotification(context, title, message, ringtoneUriString, alarmId, docId);
}
private void createNotificationChannel(Context context) {
@@ -72,13 +74,14 @@ public class AlarmReceiver extends BroadcastReceiver {
}
}
private void showNotification(Context context, String title, String message, String ringtoneUriString, int alarmId) {
private void showNotification(Context context, String title, String message, String ringtoneUriString, int alarmId, String docId) {
Intent activityIntent = new Intent(context, AlarmRingingActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
activityIntent.putExtra("alarm_title", title);
activityIntent.putExtra("alarm_time", new java.text.SimpleDateFormat("HH:mm", java.util.Locale.getDefault()).format(new java.util.Date()));
activityIntent.putExtra("ringtone_uri", ringtoneUriString);
activityIntent.putExtra("alarm_id", alarmId);
activityIntent.putExtra("alarm_doc_id", docId);
PendingIntent pendingIntent = PendingIntent.getActivity(
context,

View File

@@ -38,6 +38,7 @@ public class AlarmRingingActivity extends AppCompatActivity {
String time = getIntent().getStringExtra("alarm_time");
String ringtoneUri = getIntent().getStringExtra("ringtone_uri");
int alarmId = getIntent().getIntExtra("alarm_id", -1);
String docId = getIntent().getStringExtra("alarm_doc_id");
TextView textTitle = findViewById(R.id.textAlarmTitle);
TextView textTime = findViewById(R.id.textAlarmTime);
@@ -59,10 +60,54 @@ public class AlarmRingingActivity extends AppCompatActivity {
btnStop.setOnClickListener(v -> {
stopAlarmService();
confirmInFirestore(title, docId);
finish();
});
}
private void confirmInFirestore(String title, String docId) {
com.google.firebase.auth.FirebaseUser user = com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser();
if (user == null) return;
String uid = user.getUid();
com.google.firebase.firestore.FirebaseFirestore db = com.google.firebase.firestore.FirebaseFirestore.getInstance();
if (docId != null) {
updateAlarmDocument(db, uid, docId, title);
} else {
// Fallback to title search if docId is missing
db.collection("users").document(uid).collection("alarms")
.whereEqualTo("title", title)
.get()
.addOnSuccessListener(snapshots -> {
for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots) {
updateAlarmDocument(db, uid, doc.getId(), title);
}
});
}
}
private void updateAlarmDocument(com.google.firebase.firestore.FirebaseFirestore db, String uid, String documentId, String title) {
java.util.Map<String, Object> update = new java.util.HashMap<>();
long now = System.currentTimeMillis();
update.put("lastTakenTimestamp", now);
update.put("takenToday", true);
db.collection("users").document(uid).collection("alarms").document(documentId).update(update);
// Also add to history
String dateKey = new java.text.SimpleDateFormat("yyyyMMdd", java.util.Locale.getDefault()).format(new java.util.Date());
java.util.Map<String, Object> hist = new java.util.HashMap<>();
hist.put("date", dateKey);
hist.put("alarmId", documentId);
hist.put("title", title);
hist.put("takenAt", now);
db.collection("users").document(uid).collection("history")
.document(dateKey + "_" + documentId)
.set(hist);
}
private void snoozeAlarm(String title, String ringtoneUri, int alarmId) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (alarmManager == null) return;

View File

@@ -105,13 +105,13 @@ public class InviteCodeActivity extends AppCompatActivity {
String guardianId = currentUser.getUid();
// 1. Atualizar o perfil do responsável PRIMEIRO (ele tem permissão para o seu
// próprio perfil)
// 1. Atualizar o perfil do responsável PRIMEIRO (ele tem permissão para o seu próprio perfil)
db.collection("users").document(guardianId)
.update("managedUsers", FieldValue.arrayUnion(patientId), "type", "guardian")
.addOnSuccessListener(aVoid -> {
// 2. Tentar atualizar o perfil do paciente (pode falhar por permissões)
// 2. Tentar atualizar o perfil do paciente (pode falhar por permissões se as regras não deixarem,
// mas vamos tentar)
Map<String, Object> patientUpdate = new HashMap<>();
patientUpdate.put("guardianId", guardianId);
patientUpdate.put("guardians", FieldValue.arrayUnion(guardianId));
@@ -123,8 +123,8 @@ public class InviteCodeActivity extends AppCompatActivity {
})
.addOnFailureListener(e -> {
// Se falhar o paciente mas o responsável deu certo, avisamos mas prosseguimos
Log.e("InviteCode", "Falha ao atualizar paciente (provavelmente permissões): "
+ e.getMessage());
Log.e("InviteCode", "Falha ao atualizar paciente (provavelmente permissões): " + e.getMessage());
// Even though permissions might fail from the client side, we complete association
completeAssociation(code);
});

File diff suppressed because it is too large Load Diff

View File

@@ -51,33 +51,8 @@
android:background="@color/divider"
android:layout_marginBottom="24dp" />
<!-- Action Buttons -->
<LinearLayout
android:id="@+id/btnProfileTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="12dp">
<!-- No theme button here as per user request -->
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/ic_menu_compass"
app:tint="@color/theme_blue_primary" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="Mudar Tema"
android:textColor="@color/theme_black_primary"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/btnProfileSupport"

View File

@@ -1,5 +1,6 @@
<?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="wrap_content"
android:layout_marginBottom="12dp"
@@ -17,19 +18,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center_vertical">
<View
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/bg_service_icon" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:orientation="vertical">
android:orientation="vertical">
<TextView
android:id="@+id/textAlarmTitle"
@@ -48,7 +37,6 @@
android:text="09:00 • 100mg"
android:textColor="@color/neutral_medium"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<ImageButton
@@ -59,9 +47,9 @@
android:background="@android:color/transparent"
android:contentDescription="Editar alarme"
android:src="@android:drawable/ic_menu_edit"
android:tint="@color/primary" />
app:tint="@color/primary" />
<Switch
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switchAlarm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -74,7 +62,7 @@
android:background="@android:color/transparent"
android:contentDescription="Remover alarme"
android:src="@android:drawable/ic_menu_delete"
android:tint="@color/delete" />
app:tint="@color/delete" />
</LinearLayout>
<LinearLayout
@@ -112,5 +100,3 @@
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:padding="4dp"
android:minHeight="60dp"
android:padding="2dp"
android:minHeight="50dp"
android:gravity="center_horizontal">
<TextView

View File

@@ -8,13 +8,27 @@
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/imageViewAvatar"
<FrameLayout
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/bg_avatar"
android:padding="8dp"
android:src="@drawable/logo_bem" />
android:layout_height="40dp">
<ImageView
android:id="@+id/imageViewAvatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_avatar"
android:padding="8dp"
android:src="@drawable/logo_bem" />
<View
android:id="@+id/viewOnlineStatus"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_gravity="bottom|end"
android:background="@drawable/bg_circle_avatar"
android:backgroundTint="@color/neutral_medium"
android:visibility="gone" />
</FrameLayout>
<LinearLayout
android:layout_width="0dp"

View File

@@ -57,6 +57,9 @@
android:alpha="0.7"
android:textSize="14sp" />
<!-- Weather removed from here and moved to Reminders tab -->
</LinearLayout>
</FrameLayout>

View File

@@ -1,57 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_surface"
android:overScrollMode="never"
android:paddingBottom="32dp">
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="24dp"
android:paddingTop="32dp"
android:paddingEnd="24dp">
android:padding="20dp"
android:paddingBottom="120dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Histórico"
android:textColor="@color/neutral_dark"
android:textSize="26sp"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="20dp"
android:text="Registo de medicação tomada"
android:textColor="@color/neutral_medium"
android:textSize="14sp" />
<!-- Calendar Container -->
<!-- Calendar Card -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:background="@drawable/bg_guardian_card"
android:orientation="vertical"
android:padding="16dp">
android:padding="12dp">
<!-- Month Title -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="16dp">
android:paddingBottom="12dp">
<TextView
android:id="@+id/textMonthTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Dezembro 2024"
android:text="Março 2026"
android:textColor="@color/neutral_dark"
android:textSize="18sp"
android:textStyle="bold" />
@@ -63,92 +62,29 @@
android:tint="@color/primary" />
</LinearLayout>
<!-- Weekday Headers -->
<!-- Weekday Headers - 7 equal TextViews in a TableRow-like layout -->
<LinearLayout
android:id="@+id/weekdayHeaders"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="7">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="D"
android:textColor="@color/delete"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="S"
android:textColor="@color/neutral_medium"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="T"
android:textColor="@color/neutral_medium"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="Q"
android:textColor="@color/neutral_medium"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="Q"
android:textColor="@color/neutral_medium"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="S"
android:textColor="@color/neutral_medium"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:padding="4dp"
android:text="S"
android:textColor="@color/neutral_medium"
android:textStyle="bold" />
android:baselineAligned="false">
<!-- 7 headers added programmatically to guarantee equal width -->
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="8dp"
android:background="@color/divider"/>
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:background="@color/divider" />
<!-- Month Grid -->
<!-- Calendar Grid - rows added programmatically -->
<LinearLayout
android:id="@+id/calendarGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Rows will be added here -->
</LinearLayout>
android:orientation="vertical" />
</LinearLayout>
@@ -157,8 +93,9 @@
android:id="@+id/legendContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginTop="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -166,10 +103,8 @@
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/neutral_dark"
android:layout_marginBottom="8dp"/>
<!-- Legend items added programmatically -->
android:layout_marginBottom="8dp" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</ScrollView>

View File

@@ -21,10 +21,19 @@
android:orientation="horizontal"
android:layout_marginBottom="32dp">
<ImageButton
android:id="@+id/btnRefreshGuardian"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@android:drawable/stat_notify_sync"
android:layout_marginEnd="12dp"
app:tint="@color/theme_blue_primary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
@@ -44,7 +53,6 @@
android:textColor="@color/neutral_medium"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<!-- Summary Status Section -->