diff --git a/app/src/main/java/com/example/vdcscore/MainActivity.java b/app/src/main/java/com/example/vdcscore/MainActivity.java index 1efa816..47904c2 100644 --- a/app/src/main/java/com/example/vdcscore/MainActivity.java +++ b/app/src/main/java/com/example/vdcscore/MainActivity.java @@ -1,8 +1,12 @@ package com.example.vdcscore; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.View; import android.view.Menu; +import android.widget.ImageView; +import android.widget.TextView; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.navigation.NavigationView; @@ -15,6 +19,10 @@ import androidx.drawerlayout.widget.DrawerLayout; import androidx.appcompat.app.AppCompatActivity; import com.example.vdcscore.databinding.ActivityMainBinding; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +import java.io.InputStream; public class MainActivity extends AppCompatActivity { @@ -48,6 +56,88 @@ public class MainActivity extends AppCompatActivity { NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration); NavigationUI.setupWithNavController(navigationView, navController); + + // Carregar dados do utilizador no menu lateral + loadUserDataInNavHeader(); + } + + private void loadUserDataInNavHeader() { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if (user == null) return; + + View headerView = binding.navView.getHeaderView(0); + TextView textViewName = headerView.findViewById(R.id.textViewName); + TextView textViewEmail = headerView.findViewById(R.id.textView); + ImageView imageView = headerView.findViewById(R.id.imageView); + + // Carregar nome + if (textViewName != null) { + if (user.getDisplayName() != null && !user.getDisplayName().isEmpty()) { + textViewName.setText(user.getDisplayName()); + } else { + textViewName.setText("Utilizador"); + } + } + + // Carregar email + if (textViewEmail != null && user.getEmail() != null) { + textViewEmail.setText(user.getEmail()); + } + + // Carregar foto de perfil + if (imageView != null && user.getPhotoUrl() != null) { + loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView); + } else { + // Tentar carregar do Storage + loadProfileImageFromStorage(imageView); + } + } + + private void loadProfileImageInNavHeader(String imageUrl, ImageView imageView) { + new Thread(() -> { + InputStream input = null; + try { + java.net.URL url = new java.net.URL(imageUrl); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.connect(); + input = connection.getInputStream(); + Bitmap bitmap = BitmapFactory.decodeStream(input); + runOnUiThread(() -> { + if (bitmap != null && imageView != null) { + imageView.setImageBitmap(bitmap); + imageView.setScaleType(android.widget.ImageView.ScaleType.CENTER_CROP); + } + }); + } catch (Exception e) { + // Se falhar, tentar carregar do Storage + runOnUiThread(() -> loadProfileImageFromStorage(imageView)); + } finally { + if (input != null) { + try { + input.close(); + } catch (Exception e) { + // Ignorar erro ao fechar + } + } + } + }).start(); + } + + private void loadProfileImageFromStorage(ImageView imageView) { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if (user == null || imageView == null) return; + + com.google.firebase.storage.FirebaseStorage.getInstance() + .getReference() + .child("profile_images/" + user.getUid() + ".jpg") + .getDownloadUrl() + .addOnSuccessListener(uri -> { + loadProfileImageInNavHeader(uri.toString(), imageView); + }) + .addOnFailureListener(e -> { + // Manter imagem padrão + }); } @Override @@ -63,4 +153,11 @@ public class MainActivity extends AppCompatActivity { return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp(); } -} \ No newline at end of file + + @Override + protected void onResume() { + super.onResume(); + // Atualizar dados do utilizador quando voltar à activity + loadUserDataInNavHeader(); + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/definicoes/ContaActivity.java b/app/src/main/java/com/example/vdcscore/ui/definicoes/ContaActivity.java index 0fc45bb..b039dfb 100644 --- a/app/src/main/java/com/example/vdcscore/ui/definicoes/ContaActivity.java +++ b/app/src/main/java/com/example/vdcscore/ui/definicoes/ContaActivity.java @@ -44,8 +44,11 @@ public class ContaActivity extends AppCompatActivity { private ImageView imageProfile; private TextInputEditText editName; + private TextInputEditText editImageUrl; private TextView textEmail; private Button btnSaveName; + private Button btnLoadImageUrl; + private Button btnLogout; private View btnChangePhoto; private View cardImageContainer; @@ -57,6 +60,8 @@ public class ContaActivity extends AppCompatActivity { private ActivityResultLauncher imagePickerLauncher; private ActivityResultLauncher permissionLauncher; private Uri selectedImageUri; + + private static final String PREFS_NAME = "LoginPrefs"; @Override protected void onCreate(Bundle savedInstanceState) { @@ -88,8 +93,10 @@ public class ContaActivity extends AppCompatActivity { imageProfile = findViewById(R.id.imageProfile); editName = findViewById(R.id.editName); + editImageUrl = findViewById(R.id.editImageUrl); textEmail = findViewById(R.id.textEmail); btnSaveName = findViewById(R.id.btnSaveName); + btnLoadImageUrl = findViewById(R.id.btnLoadImageUrl); btnLogout = findViewById(R.id.btnLogout); btnChangePhoto = findViewById(R.id.btnChangePhoto); cardImageContainer = findViewById(R.id.cardImageContainer); @@ -226,11 +233,121 @@ public class ContaActivity extends AppCompatActivity { if (btnSaveName != null) { btnSaveName.setOnClickListener(v -> saveUserName()); } + if (btnLoadImageUrl != null) { + btnLoadImageUrl.setOnClickListener(v -> loadImageFromUrl()); + } if (btnLogout != null) { btnLogout.setOnClickListener(v -> logoutUser()); } } + private void loadImageFromUrl() { + if (editImageUrl == null) return; + + String imageUrl = editImageUrl.getText().toString().trim(); + + if (imageUrl.isEmpty()) { + Toast.makeText(this, "Por favor, insira uma URL válida", Toast.LENGTH_SHORT).show(); + return; + } + + if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) { + Toast.makeText(this, "URL inválida. Deve começar com http:// ou https://", Toast.LENGTH_SHORT).show(); + return; + } + + progressDialog.show(); + + // Carregar imagem da URL + new Thread(() -> { + try { + java.net.URL url = new java.net.URL(imageUrl); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.connect(); + InputStream input = connection.getInputStream(); + Bitmap bitmap = BitmapFactory.decodeStream(input); + + runOnUiThread(() -> { + progressDialog.dismiss(); + if (bitmap != null && imageProfile != null) { + imageProfile.setImageBitmap(bitmap); + // Converter bitmap para URI e fazer upload + uploadImageFromBitmap(bitmap); + } else { + Toast.makeText(this, "Erro ao carregar imagem da URL", Toast.LENGTH_SHORT).show(); + } + }); + + if (input != null) { + input.close(); + } + } catch (Exception e) { + runOnUiThread(() -> { + progressDialog.dismiss(); + Toast.makeText(this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT).show(); + }); + } + }).start(); + } + + private void uploadImageFromBitmap(Bitmap bitmap) { + FirebaseUser user = mAuth.getCurrentUser(); + if (user == null) return; + + progressDialog.show(); + + try { + // Redimensionar se muito grande + 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 -> { + profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> { + UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder() + .setPhotoUri(uri) + .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); diff --git a/app/src/main/res/layout/activity_conta.xml b/app/src/main/res/layout/activity_conta.xml index 8af0565..89a9df2 100644 --- a/app/src/main/res/layout/activity_conta.xml +++ b/app/src/main/res/layout/activity_conta.xml @@ -107,7 +107,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Alterar Foto" + android:text="Alterar Foto (Galeria)" android:textColor="#616161" android:textSize="15sp" android:textStyle="bold" @@ -116,6 +116,50 @@ android:padding="12dp" android:background="?attr/selectableItemBackgroundBorderless" /> + + + + + + + +