continuar

This commit is contained in:
MeuNome
2026-04-21 17:09:31 +01:00
parent 9ff7ada370
commit 514d3e59ec
312 changed files with 15641 additions and 16672 deletions

View File

@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".FluxupApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"

View File

@@ -22,21 +22,6 @@ public class LoginActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Inicializar Firebase e App Check antes de qualquer outra chamada
FirebaseApp.initializeApp(this);
FirebaseAppCheck firebaseAppCheck = FirebaseAppCheck.getInstance();
if (com.fluxup.app.BuildConfig.DEBUG) {
// Modo Desenvolvimento: Usa Debug Provider para gerar token no Logcat
firebaseAppCheck.installAppCheckProviderFactory(
DebugAppCheckProviderFactory.getInstance());
android.util.Log.d("FLUXUP_DEBUG", "App Check: Debug Provider instalado. Procure pelo token no Logcat.");
} else {
// Modo Produção: Usa Play Integrity
firebaseAppCheck.installAppCheckProviderFactory(
PlayIntegrityAppCheckProviderFactory.getInstance());
}
// Aplicar preferências de tema antes do super.onCreate
android.content.SharedPreferences prefs = getSharedPreferences("FluxupSettings", android.content.Context.MODE_PRIVATE);
boolean isDarkMode = prefs.getBoolean("darkMode", false);
@@ -48,8 +33,8 @@ public class LoginActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
// Verificar se o utilizador já está logado
if (com.google.firebase.auth.FirebaseAuth.getInstance().getCurrentUser() != null) {
// Verificar se o utilizador já está logado usando o AuthManager
if (AuthManager.getInstance().getCurrentUser() != null) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();

View File

@@ -9,6 +9,7 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class RegisterActivity extends AppCompatActivity {
private EditText etUsername, etEmail, etPhone, etPassword, etConfirmPassword;
@@ -16,6 +17,7 @@ public class RegisterActivity extends AppCompatActivity {
private TextView tvBackToLogin;
private android.widget.ProgressBar pbRegister;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -92,6 +94,8 @@ public class RegisterActivity extends AppCompatActivity {
return;
}
// Mostrar progresso e desativar botão
pbRegister.setVisibility(View.VISIBLE);
btnRegister.setEnabled(false);

View File

@@ -10,79 +10,58 @@ import java.util.Map;
public class UsuariosService {
private static final FirebaseAuth mAuth = FirebaseAuth.getInstance();
private static final FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();
private static AuthManager getAuthManager() {
return AuthManager.getInstance();
}
private static FirebaseFirestore getFirestore() {
return FirebaseFirestore.getInstance();
}
public static void login(Context context, String email, String password, ServiceCallback<Usuario> callback) {
android.util.Log.d("FLUXUP_SERVICE", "A tentar iniciar sessão para: " + email);
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
getAuthManager().loginUtilizador(email, password, new AuthManager.AuthCallback() {
@Override
public void onSuccess(FirebaseUser user) {
if (user != null) {
android.util.Log.d("FLUXUP_SERVICE", "Auth bem-sucedido para: " + email);
FirebaseUser user = mAuth.getCurrentUser();
if (user != null) {
Usuario defaultUsuario = new Usuario(user.getUid(), "", user.getEmail(), "", "");
defaultUsuario.id = user.getUid();
Usuario defaultUsuario = new Usuario(user.getUid(), "", user.getEmail(), "", "");
defaultUsuario.id = user.getUid();
mFirestore.collection("users").document(user.getUid()).get()
.addOnSuccessListener(documentSnapshot -> {
android.util.Log.d("FLUXUP_SERVICE", "Dados recuperados do Firestore com sucesso.");
Usuario usuario = documentSnapshot.toObject(Usuario.class);
if (usuario != null) {
callback.onSuccess(usuario);
} else {
android.util.Log.w("FLUXUP_SERVICE", "Documento do utilizador não encontrado no Firestore.");
callback.onSuccess(defaultUsuario);
}
})
.addOnFailureListener(e -> {
android.util.Log.e("FLUXUP_SERVICE", "Erro ao carregar do Firestore: " + e.getMessage());
getFirestore().collection("users").document(user.getUid()).get()
.addOnSuccessListener(documentSnapshot -> {
android.util.Log.d("FLUXUP_SERVICE", "Dados recuperados do Firestore com sucesso.");
Usuario usuario = documentSnapshot.toObject(Usuario.class);
if (usuario != null) {
callback.onSuccess(usuario);
} else {
android.util.Log.w("FLUXUP_SERVICE", "Documento do utilizador não encontrado no Firestore.");
callback.onSuccess(defaultUsuario);
});
}
} else {
android.util.Log.e("FLUXUP_SERVICE", "Falha no Auth: " + (task.getException() != null ? task.getException().getMessage() : "Desconhecido"));
String errorMsg = "Erro ao entrar";
if (task.getException() instanceof FirebaseAuthException) {
String errorCode = ((FirebaseAuthException) task.getException()).getErrorCode();
switch (errorCode) {
case "ERROR_INVALID_EMAIL":
case "ERROR_USER_NOT_FOUND":
errorMsg = "Utilizador não encontrado";
break;
case "ERROR_WRONG_PASSWORD":
errorMsg = "Palavra-passe incorreta";
break;
case "ERROR_USER_DISABLED":
errorMsg = "Este utilizador foi desativado";
break;
case "ERROR_TOO_MANY_REQUESTS":
errorMsg = "Demasiadas tentativas. Tente mais tarde";
break;
case "ERROR_INVALID_CREDENTIAL":
errorMsg = "Credenciais inválidas ou expiradas";
break;
default:
errorMsg = "Erro na autenticação: " + task.getException().getLocalizedMessage();
break;
}
} else if (task.getException() != null) {
errorMsg = task.getException().getLocalizedMessage();
}
callback.onError(errorMsg);
}
})
.addOnFailureListener(e -> {
android.util.Log.e("FLUXUP_SERVICE", "Erro ao carregar do Firestore: " + e.getMessage());
callback.onSuccess(defaultUsuario);
});
}
});
}
@Override
public void onError(String errorMessage) {
android.util.Log.e("FLUXUP_SERVICE", "Falha no Auth: " + errorMessage);
callback.onError(errorMessage);
}
});
}
public static void registar(Context context, Usuario usuario, ServiceCallback<Usuario> callback) {
android.util.Log.d("FLUXUP_SERVICE", "A tentar registar utilizador: " + usuario.email);
mAuth.createUserWithEmailAndPassword(usuario.email, usuario.palavra_passe)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
getAuthManager().registrarUtilizador(usuario.email, usuario.palavra_passe, new AuthManager.AuthCallback() {
@Override
public void onSuccess(FirebaseUser firebaseUser) {
if (firebaseUser != null) {
android.util.Log.d("FLUXUP_SERVICE", "Utilizador criado no Auth com sucesso: " + usuario.email);
FirebaseUser firebaseUser = mAuth.getCurrentUser();
if (firebaseUser != null) {
String uid = firebaseUser.getUid();
String uid = firebaseUser.getUid();
usuario.id_usuario = uid;
usuario.id = uid;
@@ -90,37 +69,28 @@ public class UsuariosService {
usuario.palavra_passe = null;
android.util.Log.d("FLUXUP_SERVICE", "A guardar utilizador no Firestore (Coleção: users, ID: " + uid + ")...");
mFirestore.collection("users").document(uid).set(usuario)
.addOnSuccessListener(aVoid -> {
android.util.Log.d("FLUXUP_SERVICE", "Utilizador guardado no Firestore com sucesso.");
usuario.palavra_passe = tempPass;
callback.onSuccess(usuario);
})
.addOnFailureListener(e -> {
android.util.Log.e("FLUXUP_SERVICE", "ERRO NO FIRESTORE: " + e.getMessage());
callback.onError("Erro ao guardar na base de dados: " + e.getMessage());
});
}
} else {
android.util.Log.e("FLUXUP_SERVICE", "Falha ao criar conta no Auth: " + (task.getException() != null ? task.getException().getMessage() : "Desconhecido"));
String errorMsg = "Erro ao criar conta";
if (task.getException() instanceof FirebaseAuthException) {
String errorCode = ((FirebaseAuthException) task.getException()).getErrorCode();
if (errorCode.equals("ERROR_EMAIL_ALREADY_IN_USE")) {
errorMsg = "Este email já está a ser utilizado";
} else {
errorMsg = task.getException().getLocalizedMessage();
}
} else if (task.getException() != null) {
errorMsg = task.getException().getLocalizedMessage();
}
callback.onError(errorMsg);
getFirestore().collection("users").document(uid).set(usuario)
.addOnSuccessListener(aVoid -> {
android.util.Log.d("FLUXUP_SERVICE", "Utilizador guardado no Firestore com sucesso.");
usuario.palavra_passe = tempPass;
callback.onSuccess(usuario);
})
.addOnFailureListener(e -> {
android.util.Log.e("FLUXUP_SERVICE", "ERRO NO FIRESTORE: " + e.getMessage());
callback.onError("Erro ao guardar na base de dados: " + e.getMessage());
});
}
});
}
@Override
public void onError(String errorMessage) {
android.util.Log.e("FLUXUP_SERVICE", "Falha ao criar conta no Auth: " + errorMessage);
callback.onError(errorMessage);
}
});
}
public static void recuperarPalavraPasse(Context context, String email, ServiceCallback<Void> callback) {
mAuth.sendPasswordResetEmail(email)
FirebaseAuth.getInstance().sendPasswordResetEmail(email)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
callback.onSuccess(null);

View File

@@ -11,7 +11,7 @@
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fluxup"
android:text="@string/app_name"
android:textColor="@color/purple_500"
android:textSize="32sp"
android:textStyle="bold"
@@ -20,7 +20,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Entre na sua conta"
android:text="@string/login_subtitle"
android:textColor="#666666"
android:textSize="16sp"
android:layout_marginBottom="24dp"/>
@@ -29,28 +29,32 @@
android:id="@+id/etEmail"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="Email"
android:hint="@string/email_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="15dp"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:layout_marginBottom="15dp"
android:inputType="textEmailAddress"/>
android:inputType="textEmailAddress"
android:autofillHints="emailAddress"/>
<EditText
android:id="@+id/etPassword"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="Palavra Passe"
android:hint="@string/password_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="15dp"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:layout_marginBottom="15dp"
android:inputType="textPassword"/>
android:inputType="textPassword"
android:autofillHints="password"/>
<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Entrar"
android:text="@string/login_button"
android:backgroundTint="@color/purple_500"
android:textColor="@color/white"
android:textAllCaps="false"
@@ -62,7 +66,7 @@
android:id="@+id/tvGoToRegister"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Não tem conta? Registe-se"
android:text="@string/no_account_register"
android:textColor="@color/purple_500"
android:padding="10dp"/>
@@ -70,7 +74,7 @@
android:id="@+id/tvForgotPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Esqueci a palavrapasse"
android:text="@string/forgot_password"
android:textColor="@color/purple_500"
android:padding="10dp"/>

View File

@@ -14,7 +14,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fluxup"
android:text="@string/app_name"
android:textColor="@color/purple_500"
android:textSize="32sp"
android:textStyle="bold"
@@ -24,7 +24,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Registar nova conta"
android:text="@string/register_title"
android:textColor="#999999"
android:textSize="16sp"
android:layout_marginBottom="30dp"/>
@@ -33,56 +33,67 @@
android:id="@+id/etRegUsername"
android:layout_width="match_parent"
android:layout_height="56dp"
android:hint="Nome de utilizador"
android:hint="@string/username_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="16dp"
android:layout_marginBottom="16dp"/>
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginBottom="16dp"
android:inputType="textPersonName"
android:autofillHints="username"/>
<EditText
android:id="@+id/etRegEmail"
android:layout_width="match_parent"
android:layout_height="56dp"
android:hint="Email"
android:hint="@string/email_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginBottom="16dp"
android:inputType="textEmailAddress"/>
android:inputType="textEmailAddress"
android:autofillHints="emailAddress"/>
<EditText
android:id="@+id/etRegPhone"
android:layout_width="match_parent"
android:layout_height="56dp"
android:hint="Número de telemóvel"
android:hint="@string/phone_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginBottom="16dp"
android:inputType="phone"/>
android:inputType="phone"
android:autofillHints="phoneNumber"/>
<EditText
android:id="@+id/etRegPassword"
android:layout_width="match_parent"
android:layout_height="56dp"
android:hint="Palavra-passe"
android:hint="@string/password_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginBottom="16dp"
android:inputType="textPassword"/>
android:inputType="textPassword"
android:autofillHints="newPassword"/>
<EditText
android:id="@+id/etRegConfirmPassword"
android:layout_width="match_parent"
android:layout_height="56dp"
android:hint="Confirmar palavra-passe"
android:hint="@string/confirm_password_hint"
android:background="@drawable/edit_text_bg"
android:paddingHorizontal="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginBottom="16dp"
android:inputType="textPassword"/>
android:inputType="textPassword"
android:autofillHints="newPassword"/>
<Button
android:id="@+id/btnRegister"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Registar"
android:text="@string/register_button"
android:backgroundTint="@color/purple_500"
android:textColor="@color/white"
android:textAllCaps="false"
@@ -108,7 +119,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Já tens conta? "
android:text="@string/already_have_account"
android:textColor="#999999"
android:textSize="16sp"/>
@@ -116,7 +127,7 @@
android:id="@+id/tvBackToLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Entrar"
android:text="@string/login_button"
android:textColor="@color/purple_500"
android:textSize="16sp"
android:textStyle="bold"/>

View File

@@ -18,4 +18,20 @@
<string name="language">Language</string>
<string name="logout">Log out</string>
<string name="back">Back</string>
<!-- Login Strings -->
<string name="login_subtitle">Log in to your account</string>
<string name="email_hint">Email</string>
<string name="password_hint">Password</string>
<string name="login_button">Login</string>
<string name="no_account_register">No account? Register</string>
<string name="forgot_password">I forgot my password</string>
<!-- Register Strings -->
<string name="register_title">Register new account</string>
<string name="username_hint">Username</string>
<string name="phone_hint">Phone number</string>
<string name="confirm_password_hint">Confirm password</string>
<string name="register_button">Register</string>
<string name="already_have_account">Already have an account? </string>
</resources>

View File

@@ -18,4 +18,20 @@
<string name="language">Idioma</string>
<string name="logout">Cerrar sesión</string>
<string name="back">Volver</string>
<!-- Login Strings -->
<string name="login_subtitle">Inicie sesión en su cuenta</string>
<string name="email_hint">Email</string>
<string name="password_hint">Contraseña</string>
<string name="login_button">Entrar</string>
<string name="no_account_register">¿No tienes cuenta? Regístrate</string>
<string name="forgot_password">Olvidé mi contraseña</string>
<!-- Register Strings -->
<string name="register_title">Registrar nueva cuenta</string>
<string name="username_hint">Nombre de usuario</string>
<string name="phone_hint">Número de móvil</string>
<string name="confirm_password_hint">Confirmar contraseña</string>
<string name="register_button">Registrar</string>
<string name="already_have_account">¿Ya tienes cuenta? </string>
</resources>

View File

@@ -18,5 +18,21 @@
<string name="language">Idioma</string>
<string name="logout">Terminar sessão</string>
<string name="back">Voltar</string>
<!-- Login Strings -->
<string name="login_subtitle">Entre na sua conta</string>
<string name="email_hint">Email</string>
<string name="password_hint">Palavra Passe</string>
<string name="login_button">Entrar</string>
<string name="no_account_register">Não tem conta? Registe-se</string>
<string name="forgot_password">Esqueci a palavra-passe</string>
<!-- Register Strings -->
<string name="register_title">Registar nova conta</string>
<string name="username_hint">Nome de utilizador</string>
<string name="phone_hint">Número de telemóvel</string>
<string name="confirm_password_hint">Confirmar palavra-passe</string>
<string name="register_button">Registar</string>
<string name="already_have_account">Já tens conta? </string>
</resources>

View File

@@ -39,7 +39,8 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">56dp</item>
<item name="android:background">@drawable/edit_text_bg</item>
<item name="android:paddingHorizontal">@dimen/spacing_md</item>
<item name="android:paddingStart">@dimen/spacing_md</item>
<item name="android:paddingEnd">@dimen/spacing_md</item>
<item name="android:textSize">@dimen/font_body</item>
<item name="android:textColor">@color/text_light</item>
<item name="android:layout_marginBottom">@dimen/spacing_md</item>