app atualizada para apresentação
This commit is contained in:
@@ -39,12 +39,18 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
checkRememberMe = findViewById(R.id.checkRememberMe);
|
checkRememberMe = findViewById(R.id.checkRememberMe);
|
||||||
criarContaTextView = findViewById(R.id.txtRegister);
|
criarContaTextView = findViewById(R.id.txtRegister);
|
||||||
txtForgotPassword = findViewById(R.id.txtForgotPassword);
|
txtForgotPassword = findViewById(R.id.txtForgotPassword);
|
||||||
|
TextView txtGuestMode = findViewById(R.id.txtGuestMode);
|
||||||
|
|
||||||
mAuth = FirebaseAuth.getInstance();
|
mAuth = FirebaseAuth.getInstance();
|
||||||
|
|
||||||
btnLogin.setOnClickListener(v -> loginUser());
|
btnLogin.setOnClickListener(v -> loginUser());
|
||||||
criarContaTextView.setOnClickListener(view -> criarConta());
|
criarContaTextView.setOnClickListener(view -> criarConta());
|
||||||
txtForgotPassword.setOnClickListener(view -> recuperarPassword());
|
txtForgotPassword.setOnClickListener(view -> recuperarPassword());
|
||||||
|
txtGuestMode.setOnClickListener(v -> {
|
||||||
|
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
|
||||||
// Carregar credenciais guardadas
|
// Carregar credenciais guardadas
|
||||||
loadSavedCredentials();
|
loadSavedCredentials();
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||||||
import com.example.vdcscore.databinding.ActivityMainBinding;
|
import com.example.vdcscore.databinding.ActivityMainBinding;
|
||||||
import com.google.firebase.auth.FirebaseAuth;
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
import com.google.firebase.auth.FirebaseUser;
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
|
import com.google.firebase.database.DataSnapshot;
|
||||||
|
import com.google.firebase.database.DatabaseError;
|
||||||
|
import com.google.firebase.database.DatabaseReference;
|
||||||
|
import com.google.firebase.database.FirebaseDatabase;
|
||||||
|
import com.google.firebase.database.ValueEventListener;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
@@ -43,6 +49,14 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private ActivityMainBinding binding;
|
private ActivityMainBinding binding;
|
||||||
private ActivityResultLauncher<String> mGetContent;
|
private ActivityResultLauncher<String> mGetContent;
|
||||||
|
|
||||||
|
private java.util.Set<String> favoriteClubs = new java.util.HashSet<>();
|
||||||
|
private DatabaseReference favoritesRef;
|
||||||
|
private ValueEventListener favoritesListener;
|
||||||
|
private DatabaseReference senioresRef;
|
||||||
|
private ValueEventListener senioresListener;
|
||||||
|
private DatabaseReference junioresRef;
|
||||||
|
private ValueEventListener junioresListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -87,6 +101,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
// Carregar dados do utilizador no menu lateral
|
// Carregar dados do utilizador no menu lateral
|
||||||
loadUserDataInNavHeader();
|
loadUserDataInNavHeader();
|
||||||
|
|
||||||
|
// Inicializar o sistema de notificações para favoritos
|
||||||
|
setupNotificationSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadUserDataInNavHeader() {
|
private void loadUserDataInNavHeader() {
|
||||||
@@ -212,4 +229,157 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// Atualizar dados do utilizador quando voltar à activity
|
// Atualizar dados do utilizador quando voltar à activity
|
||||||
loadUserDataInNavHeader();
|
loadUserDataInNavHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupNotificationSystem() {
|
||||||
|
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (user == null) return;
|
||||||
|
|
||||||
|
createNotificationChannel();
|
||||||
|
|
||||||
|
// Listen to favorites
|
||||||
|
favoritesRef = FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(user.getUid())
|
||||||
|
.child("favorites");
|
||||||
|
|
||||||
|
favoritesListener = new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
favoriteClubs.clear();
|
||||||
|
for (DataSnapshot favSnap : snapshot.getChildren()) {
|
||||||
|
if (Boolean.TRUE.equals(favSnap.getValue(Boolean.class))) {
|
||||||
|
favoriteClubs.add(favSnap.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {}
|
||||||
|
};
|
||||||
|
favoritesRef.addValueEventListener(favoritesListener);
|
||||||
|
|
||||||
|
// Listen to seniores matches
|
||||||
|
senioresRef = FirebaseDatabase.getInstance().getReference("jornadas").child("seniores");
|
||||||
|
senioresListener = new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
checkMatchesAndNotify(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {}
|
||||||
|
};
|
||||||
|
senioresRef.addValueEventListener(senioresListener);
|
||||||
|
|
||||||
|
// Listen to juniores matches
|
||||||
|
junioresRef = FirebaseDatabase.getInstance().getReference("jornadas").child("juniores");
|
||||||
|
junioresListener = new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
checkMatchesAndNotify(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {}
|
||||||
|
};
|
||||||
|
junioresRef.addValueEventListener(junioresListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMatchesAndNotify(DataSnapshot categorySnapshot) {
|
||||||
|
if (favoriteClubs.isEmpty()) return;
|
||||||
|
|
||||||
|
android.content.SharedPreferences prefs = getSharedPreferences("NotifiedMatchesPrefs", android.content.Context.MODE_PRIVATE);
|
||||||
|
android.content.SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
|
||||||
|
for (DataSnapshot jornadaSnap : categorySnapshot.getChildren()) {
|
||||||
|
for (DataSnapshot matchSnap : jornadaSnap.getChildren()) {
|
||||||
|
com.example.vdcscore.ui.gallery.Match match = matchSnap.getValue(com.example.vdcscore.ui.gallery.Match.class);
|
||||||
|
if (match != null) {
|
||||||
|
match.setId(matchSnap.getKey());
|
||||||
|
|
||||||
|
if (match.isPlayed() && match.getId() != null) {
|
||||||
|
boolean involvesFavorite = false;
|
||||||
|
String favoriteName = "";
|
||||||
|
|
||||||
|
String homeSanitized = com.example.vdcscore.utils.FirebaseErrorUtils.sanitizeKey(match.getHomeName());
|
||||||
|
String awaySanitized = com.example.vdcscore.utils.FirebaseErrorUtils.sanitizeKey(match.getAwayName());
|
||||||
|
|
||||||
|
if (homeSanitized != null && favoriteClubs.contains(homeSanitized)) {
|
||||||
|
involvesFavorite = true;
|
||||||
|
favoriteName = match.getHomeName();
|
||||||
|
} else if (awaySanitized != null && favoriteClubs.contains(awaySanitized)) {
|
||||||
|
involvesFavorite = true;
|
||||||
|
favoriteName = match.getAwayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (involvesFavorite) {
|
||||||
|
String matchPrefKey = "notified_" + match.getId();
|
||||||
|
if (!prefs.getBoolean(matchPrefKey, false)) {
|
||||||
|
// Trigger notification!
|
||||||
|
triggerLocalNotification(match, favoriteName);
|
||||||
|
// Mark as notified
|
||||||
|
editor.putBoolean(matchPrefKey, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerLocalNotification(com.example.vdcscore.ui.gallery.Match match, String favoriteClub) {
|
||||||
|
String homeScoreStr = match.getHomeScore() != null ? String.valueOf(match.getHomeScore()) : "0";
|
||||||
|
String awayScoreStr = match.getAwayScore() != null ? String.valueOf(match.getAwayScore()) : "0";
|
||||||
|
|
||||||
|
String title = "Fim de Jogo - " + favoriteClub;
|
||||||
|
String message = match.getHomeName() + " " + homeScoreStr + " - " + awayScoreStr + " " + match.getAwayName();
|
||||||
|
|
||||||
|
androidx.core.app.NotificationCompat.Builder builder = new androidx.core.app.NotificationCompat.Builder(this, "vdcscore_notifications")
|
||||||
|
.setSmallIcon(R.drawable.ic_soccer)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(message)
|
||||||
|
.setPriority(androidx.core.app.NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
.setAutoCancel(true);
|
||||||
|
|
||||||
|
// Click action: open MainActivity
|
||||||
|
android.content.Intent intent = new android.content.Intent(this, MainActivity.class);
|
||||||
|
intent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK | android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
android.app.PendingIntent pendingIntent = android.app.PendingIntent.getActivity(
|
||||||
|
this, 0, intent, android.app.PendingIntent.FLAG_UPDATE_CURRENT | android.app.PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
builder.setContentIntent(pendingIntent);
|
||||||
|
|
||||||
|
android.app.NotificationManager notificationManager = (android.app.NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);
|
||||||
|
if (notificationManager != null) {
|
||||||
|
int notificationId = match.getId().hashCode();
|
||||||
|
notificationManager.notify(notificationId, builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNotificationChannel() {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
CharSequence name = "Resultados dos Jogos";
|
||||||
|
String description = "Notificações de resultados dos jogos dos seus clubes favoritos";
|
||||||
|
int importance = android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||||
|
android.app.NotificationChannel channel = new android.app.NotificationChannel("vdcscore_notifications", name, importance);
|
||||||
|
channel.setDescription(description);
|
||||||
|
android.app.NotificationManager notificationManager = getSystemService(android.app.NotificationManager.class);
|
||||||
|
if (notificationManager != null) {
|
||||||
|
notificationManager.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (favoritesRef != null && favoritesListener != null) {
|
||||||
|
favoritesRef.removeEventListener(favoritesListener);
|
||||||
|
}
|
||||||
|
if (senioresRef != null && senioresListener != null) {
|
||||||
|
senioresRef.removeEventListener(senioresListener);
|
||||||
|
}
|
||||||
|
if (junioresRef != null && junioresListener != null) {
|
||||||
|
junioresRef.removeEventListener(junioresListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
|
import com.google.firebase.auth.FirebaseUser;
|
||||||
|
import com.example.vdcscore.LoginActivity;
|
||||||
|
|
||||||
public class ClubDetailFragment extends Fragment {
|
public class ClubDetailFragment extends Fragment {
|
||||||
|
|
||||||
@@ -33,6 +38,10 @@ public class ClubDetailFragment extends Fragment {
|
|||||||
private DatabaseReference mDatabase;
|
private DatabaseReference mDatabase;
|
||||||
private String clubId;
|
private String clubId;
|
||||||
private String escalao;
|
private String escalao;
|
||||||
|
private String currentClubName;
|
||||||
|
private boolean isFavorite = false;
|
||||||
|
private ValueEventListener favoriteListener;
|
||||||
|
private DatabaseReference favoriteRef;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
@@ -96,6 +105,8 @@ public class ClubDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void populateStats(Team team) {
|
private void populateStats(Team team) {
|
||||||
binding.textDetailClubName.setText(team.getNome());
|
binding.textDetailClubName.setText(team.getNome());
|
||||||
|
currentClubName = team.getNome();
|
||||||
|
setupFavoriteButton();
|
||||||
binding.labelStats.setVisibility(View.VISIBLE);
|
binding.labelStats.setVisibility(View.VISIBLE);
|
||||||
binding.containerStats.setVisibility(View.VISIBLE);
|
binding.containerStats.setVisibility(View.VISIBLE);
|
||||||
binding.btnCompare.setVisibility(View.VISIBLE);
|
binding.btnCompare.setVisibility(View.VISIBLE);
|
||||||
@@ -131,6 +142,8 @@ public class ClubDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void populateClubInfo(Club club) {
|
private void populateClubInfo(Club club) {
|
||||||
binding.textDetailClubName.setText(club.getName());
|
binding.textDetailClubName.setText(club.getName());
|
||||||
|
currentClubName = club.getName();
|
||||||
|
setupFavoriteButton();
|
||||||
|
|
||||||
// Bind new club info fields
|
// Bind new club info fields
|
||||||
binding.textDetailPresident.setText(club.getPresident() != null && !club.getPresident().isEmpty() ? club.getPresident() : "---");
|
binding.textDetailPresident.setText(club.getPresident() != null && !club.getPresident().isEmpty() ? club.getPresident() : "---");
|
||||||
@@ -325,9 +338,82 @@ public class ClubDetailFragment extends Fragment {
|
|||||||
binding.textCompareG2.setTypeface(null, t2.getGolos_marcados() > t1.getGolos_marcados() ? android.graphics.Typeface.BOLD : android.graphics.Typeface.NORMAL);
|
binding.textCompareG2.setTypeface(null, t2.getGolos_marcados() > t1.getGolos_marcados() ? android.graphics.Typeface.BOLD : android.graphics.Typeface.NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupFavoriteButton() {
|
||||||
|
if (currentClubName == null || binding == null) return;
|
||||||
|
|
||||||
|
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
|
||||||
|
// Remove previous listener if any
|
||||||
|
if (favoriteRef != null && favoriteListener != null) {
|
||||||
|
favoriteRef.removeEventListener(favoriteListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user != null) {
|
||||||
|
favoriteRef = FirebaseDatabase.getInstance().getReference("users")
|
||||||
|
.child(user.getUid())
|
||||||
|
.child("favorites")
|
||||||
|
.child(com.example.vdcscore.utils.FirebaseErrorUtils.sanitizeKey(currentClubName));
|
||||||
|
|
||||||
|
favoriteListener = new ValueEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
|
if (binding == null) return;
|
||||||
|
isFavorite = snapshot.exists() && Boolean.TRUE.equals(snapshot.getValue(Boolean.class));
|
||||||
|
updateFavoriteIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancelled(@NonNull DatabaseError error) {}
|
||||||
|
};
|
||||||
|
favoriteRef.addValueEventListener(favoriteListener);
|
||||||
|
} else {
|
||||||
|
isFavorite = false;
|
||||||
|
updateFavoriteIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.btnFavorite.setOnClickListener(v -> {
|
||||||
|
FirebaseUser u = FirebaseAuth.getInstance().getCurrentUser();
|
||||||
|
if (u == null) {
|
||||||
|
// Pedir para criar conta
|
||||||
|
showRegisterRequiredDialog();
|
||||||
|
} else {
|
||||||
|
// Alternar favorito
|
||||||
|
if (favoriteRef != null) {
|
||||||
|
favoriteRef.setValue(!isFavorite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFavoriteIcon() {
|
||||||
|
if (binding == null || getContext() == null) return;
|
||||||
|
if (isFavorite) {
|
||||||
|
binding.btnFavorite.setImageResource(R.drawable.ic_star);
|
||||||
|
} else {
|
||||||
|
binding.btnFavorite.setImageResource(R.drawable.ic_star_border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showRegisterRequiredDialog() {
|
||||||
|
if (getContext() == null) return;
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Iniciar Sessão Necessário")
|
||||||
|
.setMessage("Para adicionar clubes aos seus favoritos, precisa de ter uma conta com sessão iniciada. Deseja criar conta ou fazer login agora?")
|
||||||
|
.setPositiveButton("Criar Conta / Login", (dialog, which) -> {
|
||||||
|
Intent intent = new Intent(requireContext(), LoginActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
if (favoriteRef != null && favoriteListener != null) {
|
||||||
|
favoriteRef.removeEventListener(favoriteListener);
|
||||||
|
}
|
||||||
binding = null;
|
binding = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.os.Bundle;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@@ -13,8 +12,6 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||||||
import com.example.vdcscore.R;
|
import com.example.vdcscore.R;
|
||||||
import com.example.vdcscore.databinding.FragmentCupBinding;
|
import com.example.vdcscore.databinding.FragmentCupBinding;
|
||||||
import com.example.vdcscore.ui.gallery.Match;
|
import com.example.vdcscore.ui.gallery.Match;
|
||||||
import com.example.vdcscore.ui.gallery.Matchday;
|
|
||||||
import com.example.vdcscore.ui.gallery.MatchesAdapter;
|
|
||||||
import com.google.firebase.database.DataSnapshot;
|
import com.google.firebase.database.DataSnapshot;
|
||||||
import com.google.firebase.database.DatabaseError;
|
import com.google.firebase.database.DatabaseError;
|
||||||
import com.google.firebase.database.DatabaseReference;
|
import com.google.firebase.database.DatabaseReference;
|
||||||
@@ -23,26 +20,38 @@ import com.google.firebase.database.ValueEventListener;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class CupFragment extends Fragment {
|
public class CupFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentCupBinding binding;
|
private FragmentCupBinding binding;
|
||||||
private MatchesAdapter adapter;
|
private CupPhasesAdapter adapter;
|
||||||
private DatabaseReference mDatabase;
|
private DatabaseReference mDatabase;
|
||||||
private List<Matchday> phasesList = new ArrayList<>(); // Reusing Matchday as generalized 'Phase'
|
private List<CupPhase> phasesList = new ArrayList<>();
|
||||||
private int currentPhaseIndex = 0;
|
|
||||||
private String currentCategory = "seniores";
|
private String currentCategory = "seniores";
|
||||||
private ValueEventListener currentListener;
|
private ValueEventListener currentListener;
|
||||||
|
|
||||||
|
// Estrutura fixa das fases da Taça
|
||||||
|
private static final String[] CUP_PHASES_ORDER = {
|
||||||
|
"1ª Eliminatoria 1º Mão",
|
||||||
|
"2ª Eliminatoria 2º Mão",
|
||||||
|
"Quartos 1º Mão",
|
||||||
|
"Quartos 2º Mão",
|
||||||
|
"Meia Final 1º Mão",
|
||||||
|
"Meia Final 2º Mão",
|
||||||
|
"Final"
|
||||||
|
};
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
binding = FragmentCupBinding.inflate(inflater, container, false);
|
binding = FragmentCupBinding.inflate(inflater, container, false);
|
||||||
View root = binding.getRoot();
|
View root = binding.getRoot();
|
||||||
|
|
||||||
// Initialize RecyclerView with reused MatchesAdapter
|
// Initialize RecyclerView
|
||||||
adapter = new MatchesAdapter();
|
adapter = new CupPhasesAdapter();
|
||||||
binding.recyclerPhases.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerPhases.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
binding.recyclerPhases.setAdapter(adapter);
|
binding.recyclerPhases.setAdapter(adapter);
|
||||||
|
|
||||||
@@ -58,21 +67,6 @@ public class CupFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Setup Navigation Buttons
|
|
||||||
binding.btnPrevPhase.setOnClickListener(v -> {
|
|
||||||
if (currentPhaseIndex > 0) {
|
|
||||||
currentPhaseIndex--;
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.btnNextPhase.setOnClickListener(v -> {
|
|
||||||
if (currentPhaseIndex < phasesList.size() - 1) {
|
|
||||||
currentPhaseIndex++;
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial Fetch
|
// Initial Fetch
|
||||||
fetchPhases();
|
fetchPhases();
|
||||||
|
|
||||||
@@ -92,44 +86,89 @@ public class CupFragment extends Fragment {
|
|||||||
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
public void onDataChange(@NonNull DataSnapshot snapshot) {
|
||||||
if (binding == null) return;
|
if (binding == null) return;
|
||||||
|
|
||||||
phasesList.clear();
|
// Obter todas as fases do Firebase
|
||||||
|
List<String> allPhases = new ArrayList<>();
|
||||||
for (DataSnapshot phaseSnap : snapshot.getChildren()) {
|
for (DataSnapshot phaseSnap : snapshot.getChildren()) {
|
||||||
String name = phaseSnap.getKey();
|
String name = phaseSnap.getKey();
|
||||||
List<Match> matches = new ArrayList<>();
|
if (name != null) {
|
||||||
|
allPhases.add(name);
|
||||||
for (DataSnapshot matchSnap : phaseSnap.getChildren()) {
|
|
||||||
Match match = matchSnap.getValue(Match.class);
|
|
||||||
if (match != null) {
|
|
||||||
match.setId(matchSnap.getKey());
|
|
||||||
matches.add(match);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!matches.isEmpty()) {
|
|
||||||
phasesList.add(new Matchday(name, matches));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort alphabetically/chronologically as they are phrases like "1ª Fase", "Oitavos", etc.
|
if (allPhases.isEmpty()) {
|
||||||
Collections.sort(phasesList, (p1, p2) -> p1.getName().compareTo(p2.getName()));
|
binding.textPhaseName.setText("Sem fases");
|
||||||
|
adapter.setPhases(new ArrayList<>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tentar ordenar pela ordem fixa
|
||||||
|
phasesList.clear();
|
||||||
|
|
||||||
|
// Adicionar fases que estão na lista fixa (na ordem correta)
|
||||||
|
for (String fixedPhase : CUP_PHASES_ORDER) {
|
||||||
|
for (String firebasePhase : allPhases) {
|
||||||
|
if (firebasePhase.equals(fixedPhase)) {
|
||||||
|
List<Match> matches = getMatchesFromSnapshot(snapshot, firebasePhase);
|
||||||
|
if (!matches.isEmpty()) {
|
||||||
|
phasesList.add(new CupPhase(fixedPhase, matches));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adicionar fases que não estão na lista fixa (ordenadas alfabeticamente)
|
||||||
|
List<String> remainingPhases = new ArrayList<>();
|
||||||
|
for (String firebasePhase : allPhases) {
|
||||||
|
boolean isFixedPhase = false;
|
||||||
|
for (String fixed : CUP_PHASES_ORDER) {
|
||||||
|
if (fixed.equals(firebasePhase)) {
|
||||||
|
isFixedPhase = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isFixedPhase) {
|
||||||
|
remainingPhases.add(firebasePhase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(remainingPhases);
|
||||||
|
for (String remainingPhase : remainingPhases) {
|
||||||
|
List<Match> matches = getMatchesFromSnapshot(snapshot, remainingPhase);
|
||||||
|
if (!matches.isEmpty()) {
|
||||||
|
phasesList.add(new CupPhase(remainingPhase, matches));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (phasesList.isEmpty()) {
|
if (phasesList.isEmpty()) {
|
||||||
binding.textPhaseName.setText("Sem fases");
|
binding.textPhaseName.setText("Sem fases");
|
||||||
adapter.setMatches(new ArrayList<>());
|
adapter.setPhases(new ArrayList<>());
|
||||||
} else {
|
} else {
|
||||||
if (currentPhaseIndex >= phasesList.size()) {
|
binding.textPhaseName.setText(phasesList.get(0).getName());
|
||||||
currentPhaseIndex = phasesList.size() - 1;
|
adapter.setPhases(phasesList);
|
||||||
}
|
|
||||||
// In case initial load or filter swap, bound index.
|
|
||||||
if (currentPhaseIndex < 0) currentPhaseIndex = 0;
|
|
||||||
updateUI();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Match> getMatchesFromSnapshot(DataSnapshot snapshot, String phaseName) {
|
||||||
|
List<Match> matches = new ArrayList<>();
|
||||||
|
for (DataSnapshot phaseSnap : snapshot.getChildren()) {
|
||||||
|
if (phaseSnap.getKey() != null && phaseSnap.getKey().equals(phaseName)) {
|
||||||
|
for (DataSnapshot matchSnap : phaseSnap.getChildren()) {
|
||||||
|
Match match = matchSnap.getValue(Match.class);
|
||||||
|
if (match != null) {
|
||||||
|
match.setId(matchSnap.getKey());
|
||||||
|
matches.add(match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCancelled(@NonNull DatabaseError error) {
|
public void onCancelled(@NonNull DatabaseError error) {
|
||||||
if (getContext() != null) {
|
if (getContext() != null) {
|
||||||
Toast.makeText(getContext(), "Erro ao carregar taça: " + error.getMessage(), Toast.LENGTH_SHORT).show();
|
com.google.android.material.snackbar.Snackbar.make(binding.getRoot(), "Erro ao carregar taça: " + error.getMessage(), com.google.android.material.snackbar.Snackbar.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -137,22 +176,6 @@ public class CupFragment extends Fragment {
|
|||||||
mDatabase.addValueEventListener(currentListener);
|
mDatabase.addValueEventListener(currentListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUI() {
|
|
||||||
if (phasesList.isEmpty()) return;
|
|
||||||
|
|
||||||
Matchday currentPhase = phasesList.get(currentPhaseIndex);
|
|
||||||
binding.textPhaseName.setText(currentPhase.getName());
|
|
||||||
adapter.setMatches(currentPhase.getMatches());
|
|
||||||
|
|
||||||
// Enable/Disable navigation buttons
|
|
||||||
binding.btnPrevPhase.setEnabled(currentPhaseIndex > 0);
|
|
||||||
binding.btnNextPhase.setEnabled(currentPhaseIndex < phasesList.size() - 1);
|
|
||||||
|
|
||||||
// Visual feedback
|
|
||||||
binding.btnPrevPhase.setAlpha(currentPhaseIndex > 0 ? 1.0f : 0.3f);
|
|
||||||
binding.btnNextPhase.setAlpha(currentPhaseIndex < phasesList.size() - 1 ? 1.0f : 0.3f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.example.vdcscore.R;
|
import com.example.vdcscore.R;
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -90,17 +88,7 @@ public class MatchesAdapter extends RecyclerView.Adapter<MatchesAdapter.ViewHold
|
|||||||
String stadium = match.getStadium();
|
String stadium = match.getStadium();
|
||||||
holder.textStadium.setText(isValid(stadium) ? "Campo: " + stadium : "Campo a definir");
|
holder.textStadium.setText(isValid(stadium) ? "Campo: " + stadium : "Campo a definir");
|
||||||
|
|
||||||
// Match Report Button
|
// Botão de Ficha de Jogo removido
|
||||||
if (isValid(match.getMatchReportUrl())) {
|
|
||||||
holder.btnMatchReport.setVisibility(View.VISIBLE);
|
|
||||||
holder.btnMatchReport.setOnClickListener(v -> {
|
|
||||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(match.getMatchReportUrl()));
|
|
||||||
holder.itemView.getContext().startActivity(browserIntent);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
holder.btnMatchReport.setVisibility(View.GONE);
|
|
||||||
holder.btnMatchReport.setOnClickListener(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValid(String text) {
|
private boolean isValid(String text) {
|
||||||
@@ -121,8 +109,6 @@ public class MatchesAdapter extends RecyclerView.Adapter<MatchesAdapter.ViewHold
|
|||||||
public final TextView textStadium;
|
public final TextView textStadium;
|
||||||
public final ImageView imgHomeLogo;
|
public final ImageView imgHomeLogo;
|
||||||
public final ImageView imgAwayLogo;
|
public final ImageView imgAwayLogo;
|
||||||
public final com.google.android.material.button.MaterialButton btnMatchReport;
|
|
||||||
|
|
||||||
public ViewHolder(View view) {
|
public ViewHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
textHomeTeam = view.findViewById(R.id.text_home_team);
|
textHomeTeam = view.findViewById(R.id.text_home_team);
|
||||||
@@ -133,7 +119,6 @@ public class MatchesAdapter extends RecyclerView.Adapter<MatchesAdapter.ViewHold
|
|||||||
textStadium = view.findViewById(R.id.text_match_stadium);
|
textStadium = view.findViewById(R.id.text_match_stadium);
|
||||||
imgHomeLogo = view.findViewById(R.id.img_home_logo);
|
imgHomeLogo = view.findViewById(R.id.img_home_logo);
|
||||||
imgAwayLogo = view.findViewById(R.id.img_away_logo);
|
imgAwayLogo = view.findViewById(R.id.img_away_logo);
|
||||||
btnMatchReport = view.findViewById(R.id.btn_match_report);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,6 +204,21 @@
|
|||||||
android:focusable="true"/>
|
android:focusable="true"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Usar sem conta -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txtGuestMode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:fontFamily="@font/font_ibm_plex_sans"
|
||||||
|
android:text="Usar a app sem conta"
|
||||||
|
android:textColor="@color/text_2"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,20 @@
|
|||||||
tools:src="@mipmap/ic_launcher_round"/>
|
tools:src="@mipmap/ic_launcher_round"/>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<!-- Botão de Favorito -->
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btn_favorite"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Favorito"
|
||||||
|
android:src="@drawable/ic_star_border"
|
||||||
|
app:tint="@color/brand"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<!-- CLUBE Label -->
|
<!-- CLUBE Label -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/label_club"
|
android:id="@+id/label_club"
|
||||||
|
|||||||
@@ -167,26 +167,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Match Report Button (Footer style) -->
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btn_match_report"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="38dp"
|
|
||||||
android:layout_marginHorizontal="14dp"
|
|
||||||
android:layout_marginBottom="14dp"
|
|
||||||
android:backgroundTint="@color/bg_elevated"
|
|
||||||
app:strokeColor="@color/border"
|
|
||||||
app:strokeWidth="1dp"
|
|
||||||
android:fontFamily="@font/font_ibm_plex_sans"
|
|
||||||
android:text="Ficha de Jogo"
|
|
||||||
android:textColor="@color/text_2"
|
|
||||||
android:textSize="11sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:insetTop="0dp"
|
|
||||||
android:insetBottom="0dp"
|
|
||||||
app:cornerRadius="6dp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/nav_live_games"
|
android:id="@+id/nav_live_games"
|
||||||
android:icon="@drawable/ic_nav_live"
|
android:icon="@drawable/ic_nav_live"
|
||||||
android:title="@string/menu_live_games" />
|
android:title="@string/menu_live_games"
|
||||||
|
android:visible="false" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_clubs"
|
android:id="@+id/nav_clubs"
|
||||||
android:icon="@drawable/ic_nav_clubs"
|
android:icon="@drawable/ic_nav_clubs"
|
||||||
|
|||||||
Reference in New Issue
Block a user