melhoramento da app
parent
460b719785
commit
4b766067f4
|
|
@ -30,12 +30,14 @@ public class CriarContaActivity extends AppCompatActivity {
|
||||||
});
|
});
|
||||||
TextInputEditText editPassword2;
|
TextInputEditText editPassword2;
|
||||||
TextInputEditText editEmail;
|
TextInputEditText editEmail;
|
||||||
|
TextInputEditText editUserName;
|
||||||
TextInputEditText editConfirmPassword;
|
TextInputEditText editConfirmPassword;
|
||||||
Button btnCreateAccount;
|
Button btnCreateAccount;
|
||||||
TextView txtGoLogin;
|
TextView txtGoLogin;
|
||||||
|
|
||||||
|
|
||||||
editEmail = findViewById(R.id.editEmail);
|
editEmail = findViewById(R.id.editEmail);
|
||||||
|
editUserName = findViewById(R.id.editUserName);
|
||||||
editPassword2 = findViewById(R.id.editPassword2);
|
editPassword2 = findViewById(R.id.editPassword2);
|
||||||
editConfirmPassword = findViewById(R.id.editConfirmPassword);
|
editConfirmPassword = findViewById(R.id.editConfirmPassword);
|
||||||
btnCreateAccount = findViewById(R.id.btnCreateAccount);
|
btnCreateAccount = findViewById(R.id.btnCreateAccount);
|
||||||
|
|
@ -46,10 +48,11 @@ public class CriarContaActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
String email = editEmail.getText().toString().trim();
|
String email = editEmail.getText().toString().trim();
|
||||||
|
String userName = editUserName.getText().toString().trim();
|
||||||
String pass = editPassword2.getText().toString().trim();
|
String pass = editPassword2.getText().toString().trim();
|
||||||
String conf = editConfirmPassword.getText().toString().trim();
|
String conf = editConfirmPassword.getText().toString().trim();
|
||||||
|
|
||||||
if (email.isEmpty() || pass.isEmpty() || conf.isEmpty()) {
|
if (email.isEmpty() || userName.isEmpty() || pass.isEmpty() || conf.isEmpty()) {
|
||||||
Toast.makeText(CriarContaActivity.this, "Preencha todos os campos!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(CriarContaActivity.this, "Preencha todos os campos!", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -62,10 +65,24 @@ public class CriarContaActivity extends AppCompatActivity {
|
||||||
FirebaseAuth auth = FirebaseAuth.getInstance();
|
FirebaseAuth auth = FirebaseAuth.getInstance();
|
||||||
auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> {
|
auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> {
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
|
// Atualizar nome de utilizador
|
||||||
|
com.google.firebase.auth.FirebaseUser user = auth.getCurrentUser();
|
||||||
|
if (user != null) {
|
||||||
|
com.google.firebase.auth.UserProfileChangeRequest profileUpdates =
|
||||||
|
new com.google.firebase.auth.UserProfileChangeRequest.Builder()
|
||||||
|
.setDisplayName(userName)
|
||||||
|
.build();
|
||||||
|
|
||||||
Intent intent= new Intent(CriarContaActivity.this, MainActivity.class);
|
user.updateProfile(profileUpdates).addOnCompleteListener(updateTask -> {
|
||||||
|
Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
String errorMessage = "Erro ao criar conta!";
|
String errorMessage = "Erro ao criar conta!";
|
||||||
if (task.getException() != null && task.getException().getMessage() != null) {
|
if (task.getException() != null && task.getException().getMessage() != null) {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
View headerView = binding.navView.getHeaderView(0);
|
View headerView = binding.navView.getHeaderView(0);
|
||||||
TextView textViewName = headerView.findViewById(R.id.textViewName);
|
TextView textViewName = headerView.findViewById(R.id.textViewName);
|
||||||
TextView textViewEmail = headerView.findViewById(R.id.textView);
|
|
||||||
ImageView imageView = headerView.findViewById(R.id.imageView);
|
ImageView imageView = headerView.findViewById(R.id.imageView);
|
||||||
|
|
||||||
// Carregar nome
|
// Carregar nome
|
||||||
|
|
@ -79,19 +78,16 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carregar email
|
|
||||||
if (textViewEmail != null && user.getEmail() != null) {
|
|
||||||
textViewEmail.setText(user.getEmail());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carregar foto de perfil
|
// Carregar foto de perfil
|
||||||
if (imageView != null && user.getPhotoUrl() != null) {
|
if (imageView != null) {
|
||||||
|
if (user.getPhotoUrl() != null) {
|
||||||
loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView);
|
loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView);
|
||||||
} else {
|
} else {
|
||||||
// Tentar carregar do Storage
|
// Tentar carregar do Storage
|
||||||
loadProfileImageFromStorage(imageView);
|
loadProfileImageFromStorage(imageView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadProfileImageInNavHeader(String imageUrl, ImageView imageView) {
|
private void loadProfileImageInNavHeader(String imageUrl, ImageView imageView) {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.example.vdcscore.ui.definicoes;
|
package com.example.vdcscore.ui.definicoes;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
|
@ -46,8 +47,10 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
private TextInputEditText editName;
|
private TextInputEditText editName;
|
||||||
private TextInputEditText editImageUrl;
|
private TextInputEditText editImageUrl;
|
||||||
private TextView textEmail;
|
private TextView textEmail;
|
||||||
private Button btnSaveName;
|
private Button btnSaveAll;
|
||||||
private Button btnLoadImageUrl;
|
private Button btnLoadImageUrl;
|
||||||
|
private Button btnChangeEmail;
|
||||||
|
private Button btnChangePassword;
|
||||||
private Button btnLogout;
|
private Button btnLogout;
|
||||||
private View btnChangePhoto;
|
private View btnChangePhoto;
|
||||||
private View cardImageContainer;
|
private View cardImageContainer;
|
||||||
|
|
@ -60,6 +63,7 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
private ActivityResultLauncher<Intent> imagePickerLauncher;
|
||||||
private ActivityResultLauncher<String> permissionLauncher;
|
private ActivityResultLauncher<String> permissionLauncher;
|
||||||
private Uri selectedImageUri;
|
private Uri selectedImageUri;
|
||||||
|
private String imageUrlFromGoogle;
|
||||||
|
|
||||||
private static final String PREFS_NAME = "LoginPrefs";
|
private static final String PREFS_NAME = "LoginPrefs";
|
||||||
|
|
||||||
|
|
@ -95,8 +99,10 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
editName = findViewById(R.id.editName);
|
editName = findViewById(R.id.editName);
|
||||||
editImageUrl = findViewById(R.id.editImageUrl);
|
editImageUrl = findViewById(R.id.editImageUrl);
|
||||||
textEmail = findViewById(R.id.textEmail);
|
textEmail = findViewById(R.id.textEmail);
|
||||||
btnSaveName = findViewById(R.id.btnSaveName);
|
btnSaveAll = findViewById(R.id.btnSaveAll);
|
||||||
btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl);
|
btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl);
|
||||||
|
btnChangeEmail = findViewById(R.id.btnChangeEmail);
|
||||||
|
btnChangePassword = findViewById(R.id.btnChangePassword);
|
||||||
btnLogout = findViewById(R.id.btnLogout);
|
btnLogout = findViewById(R.id.btnLogout);
|
||||||
btnChangePhoto = findViewById(R.id.btnChangePhoto);
|
btnChangePhoto = findViewById(R.id.btnChangePhoto);
|
||||||
cardImageContainer = findViewById(R.id.cardImageContainer);
|
cardImageContainer = findViewById(R.id.cardImageContainer);
|
||||||
|
|
@ -180,8 +186,6 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadProfileImage(String imageUrl) {
|
private void loadProfileImage(String imageUrl) {
|
||||||
// Usar uma biblioteca de imagens seria ideal aqui (Glide/Picasso)
|
|
||||||
// Por agora, vamos usar uma abordagem simples com Thread
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
InputStream input = null;
|
InputStream input = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -197,7 +201,6 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Se falhar, tentar carregar do Storage
|
|
||||||
runOnUiThread(() -> loadProfileImageFromStorage());
|
runOnUiThread(() -> loadProfileImageFromStorage());
|
||||||
} finally {
|
} finally {
|
||||||
if (input != null) {
|
if (input != null) {
|
||||||
|
|
@ -230,14 +233,35 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
if (cardImageContainer != null) {
|
if (cardImageContainer != null) {
|
||||||
cardImageContainer.setOnClickListener(v -> openImagePicker());
|
cardImageContainer.setOnClickListener(v -> openImagePicker());
|
||||||
}
|
}
|
||||||
if (btnSaveName != null) {
|
if (btnSaveAll != null) {
|
||||||
btnSaveName.setOnClickListener(v -> saveUserName());
|
btnSaveAll.setOnClickListener(v -> saveAllChanges());
|
||||||
}
|
}
|
||||||
if (btnLoadImageUrl != null) {
|
if (btnLoadImageUrl != null) {
|
||||||
btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl());
|
btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl());
|
||||||
}
|
}
|
||||||
|
if (btnChangeEmail != null) {
|
||||||
|
btnChangeEmail.setOnClickListener(v -> sendEmailVerificationForEmailChange());
|
||||||
|
}
|
||||||
|
if (btnChangePassword != null) {
|
||||||
|
btnChangePassword.setOnClickListener(v -> sendPasswordResetEmail());
|
||||||
|
}
|
||||||
if (btnLogout != null) {
|
if (btnLogout != null) {
|
||||||
btnLogout.setOnClickListener(v -> logoutUser());
|
btnLogout.setOnClickListener(v -> showLogoutConfirmation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openImagePicker() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
|
imagePickerLauncher.launch(intent);
|
||||||
|
} else {
|
||||||
|
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||||
|
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
|
imagePickerLauncher.launch(intent);
|
||||||
|
} else {
|
||||||
|
permissionLauncher.launch(permission);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,8 +296,10 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
if (bitmap != null && imageProfile != null) {
|
if (bitmap != null && imageProfile != null) {
|
||||||
imageProfile.setImageBitmap(bitmap);
|
imageProfile.setImageBitmap(bitmap);
|
||||||
// Converter bitmap para URI e fazer upload
|
// Guardar URL para usar diretamente no perfil
|
||||||
uploadImageFromBitmap(bitmap);
|
imageUrlFromGoogle = imageUrl;
|
||||||
|
// Atualizar perfil com a URL diretamente
|
||||||
|
updateProfileWithImageUrl(imageUrl);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
@ -291,13 +317,60 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uploadImageFromBitmap(Bitmap bitmap) {
|
private void updateProfileWithImageUrl(String imageUrl) {
|
||||||
FirebaseUser user = mAuth.getCurrentUser();
|
FirebaseUser user = mAuth.getCurrentUser();
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
|
|
||||||
progressDialog.show();
|
progressDialog.show();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Uri imageUri = Uri.parse(imageUrl);
|
||||||
|
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
|
||||||
|
.setPhotoUri(imageUri)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
||||||
|
progressDialog.dismiss();
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
Toast.makeText(this, "Foto de perfil atualizada com sucesso!", Toast.LENGTH_SHORT).show();
|
||||||
|
editImageUrl.setText("");
|
||||||
|
loadProfileImage(imageUrl);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "Erro ao atualizar foto: " +
|
||||||
|
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
progressDialog.dismiss();
|
||||||
|
Toast.makeText(this, "Erro ao processar URL: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadProfileImage() {
|
||||||
|
if (selectedImageUri == null) return;
|
||||||
|
|
||||||
|
FirebaseUser user = mAuth.getCurrentUser();
|
||||||
|
if (user == null) return;
|
||||||
|
|
||||||
|
progressDialog.show();
|
||||||
|
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = getContentResolver().openInputStream(selectedImageUri);
|
||||||
|
if (inputStream == null) {
|
||||||
|
progressDialog.dismiss();
|
||||||
|
Toast.makeText(this, "Erro ao abrir imagem", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||||
|
if (bitmap == null) {
|
||||||
|
progressDialog.dismiss();
|
||||||
|
Toast.makeText(this, "Erro ao processar imagem", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Redimensionar se muito grande
|
// Redimensionar se muito grande
|
||||||
int maxSize = 1024;
|
int maxSize = 1024;
|
||||||
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
|
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
|
||||||
|
|
@ -321,121 +394,6 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
.setPhotoUri(uri)
|
.setPhotoUri(uri)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
if (task.isSuccessful()) {
|
|
||||||
Toast.makeText(this, "Foto de perfil atualizada com sucesso!", Toast.LENGTH_SHORT).show();
|
|
||||||
editImageUrl.setText("");
|
|
||||||
loadProfileImage(uri.toString());
|
|
||||||
} else {
|
|
||||||
Toast.makeText(this, "Erro ao atualizar foto: " +
|
|
||||||
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).addOnFailureListener(e -> {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
Toast.makeText(this, "Erro ao obter URL da imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
|
||||||
});
|
|
||||||
}).addOnFailureListener(e -> {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
Toast.makeText(this, "Erro ao fazer upload: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
Toast.makeText(this, "Erro ao processar imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logoutUser() {
|
|
||||||
// Limpar credenciais guardadas
|
|
||||||
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
|
||||||
editor.clear();
|
|
||||||
editor.apply();
|
|
||||||
|
|
||||||
// Fazer logout do Firebase
|
|
||||||
mAuth.signOut();
|
|
||||||
|
|
||||||
Toast.makeText(this, "Sessão terminada", Toast.LENGTH_SHORT).show();
|
|
||||||
|
|
||||||
// Voltar para o login
|
|
||||||
Intent intent = new Intent(ContaActivity.this, LoginActivity.class);
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openImagePicker() {
|
|
||||||
// No Android 13+ (API 33+), ACTION_PICK não requer permissão
|
|
||||||
// Mas vamos verificar e pedir permissão se necessário para versões anteriores
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
||||||
// Android 13+ - não precisa de permissão para ACTION_PICK
|
|
||||||
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
||||||
imagePickerLauncher.launch(intent);
|
|
||||||
} else {
|
|
||||||
// Android 12 e anteriores - precisa de permissão
|
|
||||||
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
|
|
||||||
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
||||||
imagePickerLauncher.launch(intent);
|
|
||||||
} else {
|
|
||||||
permissionLauncher.launch(permission);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void uploadProfileImage() {
|
|
||||||
if (selectedImageUri == null) return;
|
|
||||||
|
|
||||||
FirebaseUser user = mAuth.getCurrentUser();
|
|
||||||
if (user == null) return;
|
|
||||||
|
|
||||||
progressDialog.show();
|
|
||||||
|
|
||||||
InputStream inputStream = null;
|
|
||||||
try {
|
|
||||||
// Comprimir imagem
|
|
||||||
inputStream = getContentResolver().openInputStream(selectedImageUri);
|
|
||||||
if (inputStream == null) {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
Toast.makeText(this, "Erro ao abrir imagem", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
|
||||||
if (bitmap == null) {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
Toast.makeText(this, "Erro ao processar imagem", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redimensionar se muito grande (max 1024x1024)
|
|
||||||
int maxSize = 1024;
|
|
||||||
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
|
|
||||||
float scale = Math.min((float) maxSize / bitmap.getWidth(), (float) maxSize / bitmap.getHeight());
|
|
||||||
int newWidth = Math.round(bitmap.getWidth() * scale);
|
|
||||||
int newHeight = Math.round(bitmap.getHeight() * scale);
|
|
||||||
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
|
|
||||||
byte[] imageData = baos.toByteArray();
|
|
||||||
|
|
||||||
// Upload para Firebase Storage
|
|
||||||
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
|
|
||||||
UploadTask uploadTask = profileImageRef.putBytes(imageData);
|
|
||||||
|
|
||||||
uploadTask.addOnSuccessListener(taskSnapshot -> {
|
|
||||||
// Obter URL da imagem
|
|
||||||
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
|
|
||||||
// Atualizar perfil do utilizador com a URL da foto
|
|
||||||
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
|
|
||||||
.setPhotoUri(uri)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
|
|
@ -470,7 +428,7 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveUserName() {
|
private void saveAllChanges() {
|
||||||
if (editName == null) return;
|
if (editName == null) return;
|
||||||
|
|
||||||
String newName = editName.getText().toString().trim();
|
String newName = editName.getText().toString().trim();
|
||||||
|
|
@ -495,12 +453,104 @@ public class ContaActivity extends AppCompatActivity {
|
||||||
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
if (task.isSuccessful()) {
|
if (task.isSuccessful()) {
|
||||||
Toast.makeText(this, "Nome atualizado com sucesso!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "Alterações guardadas com sucesso!", Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "Erro ao atualizar nome: " +
|
Toast.makeText(this, "Erro ao guardar alterações: " +
|
||||||
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
|
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendPasswordResetEmail() {
|
||||||
|
FirebaseUser user = mAuth.getCurrentUser();
|
||||||
|
if (user == null || user.getEmail() == null) {
|
||||||
|
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressDialog.show();
|
||||||
|
|
||||||
|
mAuth.sendPasswordResetEmail(user.getEmail())
|
||||||
|
.addOnCompleteListener(task -> {
|
||||||
|
progressDialog.dismiss();
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
Toast.makeText(this,
|
||||||
|
"Email de alteração de password enviado! Verifique a sua caixa de entrada.",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
String errorMessage = "Erro ao enviar email!";
|
||||||
|
if (task.getException() != null && task.getException().getMessage() != null) {
|
||||||
|
errorMessage = "Erro: " + task.getException().getMessage();
|
||||||
|
}
|
||||||
|
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendEmailVerificationForEmailChange() {
|
||||||
|
FirebaseUser user = mAuth.getCurrentUser();
|
||||||
|
if (user == null || user.getEmail() == null) {
|
||||||
|
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressDialog.show();
|
||||||
|
|
||||||
|
// Enviar email de verificação para alterar email
|
||||||
|
user.sendEmailVerification()
|
||||||
|
.addOnCompleteListener(task -> {
|
||||||
|
progressDialog.dismiss();
|
||||||
|
if (task.isSuccessful()) {
|
||||||
|
Toast.makeText(this,
|
||||||
|
"Email de verificação enviado! Verifique a sua caixa de entrada para alterar o email.",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
// Se não conseguir enviar email de verificação, enviar email de reset de password
|
||||||
|
// que pode ser usado para alterar o email através do Firebase Console
|
||||||
|
mAuth.sendPasswordResetEmail(user.getEmail())
|
||||||
|
.addOnCompleteListener(resetTask -> {
|
||||||
|
if (resetTask.isSuccessful()) {
|
||||||
|
Toast.makeText(this,
|
||||||
|
"Email enviado! Verifique a sua caixa de entrada para instruções de alteração.",
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
String errorMessage = "Erro ao enviar email!";
|
||||||
|
if (resetTask.getException() != null && resetTask.getException().getMessage() != null) {
|
||||||
|
errorMessage = "Erro: " + resetTask.getException().getMessage();
|
||||||
|
}
|
||||||
|
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showLogoutConfirmation() {
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle("Terminar Sessão")
|
||||||
|
.setMessage("Tem a certeza que deseja terminar a sessão?")
|
||||||
|
.setPositiveButton("Sim", (dialog, which) -> logoutUser())
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logoutUser() {
|
||||||
|
// Limpar credenciais guardadas
|
||||||
|
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
editor.clear();
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
// Fazer logout do Firebase
|
||||||
|
mAuth.signOut();
|
||||||
|
|
||||||
|
Toast.makeText(this, "Sessão terminada", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
// Voltar para o login
|
||||||
|
Intent intent = new Intent(ContaActivity.this, LoginActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Nome"
|
android:text="Nome de Utilizador"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="#1A1A1A"
|
android:textColor="#1A1A1A"
|
||||||
|
|
@ -219,29 +219,16 @@
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<!-- Save Name Button -->
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnSaveName"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:backgroundTint="#424242"
|
|
||||||
android:text="Guardar Nome"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:elevation="2dp"
|
|
||||||
android:stateListAnimator="@null" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
<!-- Email Display (Read-only) -->
|
<!-- Email Section -->
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/cardEmail"
|
android:id="@+id/cardEmail"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
app:cardCornerRadius="20dp"
|
app:cardCornerRadius="20dp"
|
||||||
app:cardElevation="4dp"
|
app:cardElevation="4dp"
|
||||||
app:cardBackgroundColor="#FFFFFF"
|
app:cardBackgroundColor="#FFFFFF"
|
||||||
|
|
@ -271,7 +258,94 @@
|
||||||
android:textColor="#757575"
|
android:textColor="#757575"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:background="#F5F5F5"
|
android:background="#F5F5F5"
|
||||||
android:layout_marginTop="4dp" />
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnChangeEmail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:backgroundTint="#616161"
|
||||||
|
android:text="Alterar Email"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:stateListAnimator="@null" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<!-- Password Section -->
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/cardPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
app:cardCornerRadius="20dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:cardBackgroundColor="#FFFFFF"
|
||||||
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Password"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#1A1A1A"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnChangePassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:backgroundTint="#616161"
|
||||||
|
android:text="Alterar Password"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:stateListAnimator="@null" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<!-- Save All Changes Button -->
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/cardSaveAll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
app:cardCornerRadius="20dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:cardBackgroundColor="#FFFFFF"
|
||||||
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnSaveAll"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:backgroundTint="#424242"
|
||||||
|
android:text="Guardar Alterações"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:stateListAnimator="@null" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,36 @@
|
||||||
android:textColor="#757575"
|
android:textColor="#757575"
|
||||||
android:layout_marginBottom="32dp" />
|
android:layout_marginBottom="32dp" />
|
||||||
|
|
||||||
|
<!-- Nome de Utilizador Input -->
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:hint="Nome de Utilizador"
|
||||||
|
app:boxCornerRadiusTopStart="12dp"
|
||||||
|
app:boxCornerRadiusTopEnd="12dp"
|
||||||
|
app:boxCornerRadiusBottomStart="12dp"
|
||||||
|
app:boxCornerRadiusBottomEnd="12dp"
|
||||||
|
app:boxStrokeWidth="1dp"
|
||||||
|
app:boxStrokeColor="#BDBDBD"
|
||||||
|
app:startIconDrawable="@android:drawable/ic_menu_myplaces"
|
||||||
|
app:startIconTint="#616161"
|
||||||
|
app:boxBackgroundMode="outline"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/editUserName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:textColorHint="#9E9E9E"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:padding="18dp"
|
||||||
|
android:background="@android:color/transparent" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<!-- Email Input -->
|
<!-- Email Input -->
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/nav_header_height"
|
android:layout_height="@dimen/nav_header_height"
|
||||||
android:background="@drawable/side_nav_bar"
|
android:background="#FFFFFF"
|
||||||
android:gravity="bottom"
|
android:gravity="bottom"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
|
@ -29,14 +29,6 @@
|
||||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||||
android:text="@string/nav_header_title"
|
android:text="@string/nav_header_title"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#212121"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/nav_header_subtitle"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:alpha="0.9" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
Loading…
Reference in New Issue