Creacion de nuevas clases y de nuevos xml, funcionamiento de la api de animelist , tambien ya se consume los datos del anime list y ya puedo adaptar el anime, es decir puedo añadir y editar flata por implementar eliminar!
This commit is contained in:
parent
a040e9c755
commit
8d22a6d7da
|
|
@ -63,4 +63,6 @@ dependencies {
|
|||
|
||||
// (Opcional) Logging para depurar peticiones
|
||||
implementation ("com.squareup.okhttp3:logging-interceptor:4.9.0")
|
||||
|
||||
implementation ("com.google.code.gson:gson:2.10.1")
|
||||
}
|
||||
|
|
@ -13,9 +13,10 @@
|
|||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:theme="@style/Theme.YomiTrack"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
tools:targetApi="31">
|
||||
tools:targetApi="33">
|
||||
|
||||
|
||||
<!-- PANTALLA INICIAL: SplashActivity -->
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -3,9 +3,15 @@ package com.santiparra.yomitrack.api;
|
|||
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||
import com.santiparra.yomitrack.db.entities.UserEntity;
|
||||
import com.santiparra.yomitrack.model.AniListAnime;
|
||||
import com.santiparra.yomitrack.model.AniListMedia;
|
||||
import com.santiparra.yomitrack.model.AnimePageResponse;
|
||||
import com.santiparra.yomitrack.model.LoginResponse;
|
||||
import com.santiparra.yomitrack.model.MangaPageResponse;
|
||||
import com.santiparra.yomitrack.model.RegisterResponse;
|
||||
import com.santiparra.yomitrack.model.UserStatsResponse;
|
||||
import com.santiparra.yomitrack.utils.ActivityLog;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -23,7 +29,7 @@ public interface ApiService {
|
|||
|
||||
// ---------------- Usuario ----------------
|
||||
@POST("users/register")
|
||||
Call<RegisterResponse> registerUser(@Body Map<String, String> request);
|
||||
Call<RegisterResponse> registerUser(@Body UserEntity user);
|
||||
@POST("users/login")
|
||||
Call<LoginResponse> loginUser(@Body UserEntity user);
|
||||
|
||||
|
|
@ -34,6 +40,14 @@ public interface ApiService {
|
|||
@GET("anime/list/{userId}")
|
||||
Call<List<AnimeEntity>> getAnimeByUser(@Path("userId") int userId);
|
||||
|
||||
// Scroll infinito: obtener lista paginada
|
||||
@GET("/anime/list/{userId}")
|
||||
Call<AnimePageResponse> getAnimes(
|
||||
@Path("userId") int userId,
|
||||
@Query("page") int page,
|
||||
@Query("size") int size
|
||||
);
|
||||
|
||||
@PUT("anime/{id}")
|
||||
Call<String> updateAnime(@Path("id") int animeId, @Body AnimeEntity anime);
|
||||
|
||||
|
|
@ -47,16 +61,33 @@ public interface ApiService {
|
|||
@GET("manga/list/{userId}")
|
||||
Call<List<MangaEntity>> getMangaByUser(@Path("userId") int userId);
|
||||
|
||||
@GET("/manga/list/{userId}")
|
||||
Call<MangaPageResponse> getMangas(
|
||||
@Path("userId") int userId,
|
||||
@Query("page") int page,
|
||||
@Query("size") int size
|
||||
);
|
||||
|
||||
@PUT("manga/{id}")
|
||||
Call<String> updateManga(@Path("id") int mangaId, @Body MangaEntity manga);
|
||||
|
||||
@DELETE("manga/delete/{id}")
|
||||
Call<String> deleteManga(@Path("id") int id);
|
||||
|
||||
// ---------------- AniList API ----------------
|
||||
@GET("/anilist/search")
|
||||
Call<List<AniListAnime>> searchAnimeAniList(@Query("query") String query);
|
||||
// ---------------- Activity -------------------
|
||||
|
||||
@GET("user/{id}/stats")
|
||||
Call<Map<String, Map<String, Integer>>> getUserStats(@Path("id") int userId);
|
||||
|
||||
@GET("api/activity/list/{userId}")
|
||||
Call<List<ActivityLog>> getActivityLog(@Path("userId") int userId);
|
||||
@POST("activity/add")
|
||||
Call<JSONObject> postActivity(@Body Map<String, Object> body);
|
||||
|
||||
|
||||
// ---------------- AniList API ----------------
|
||||
|
||||
@GET("anilist/search")
|
||||
Call<List<AniListMedia>> searchAniList(@Query("query") String query, @Query("type") String type);
|
||||
|
||||
@GET("anilist/search/manga")
|
||||
Call<List<AniListAnime>> searchMangaAniList(@Query("query") String query);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,37 +15,79 @@ public class AnimeEntity implements Serializable {
|
|||
private String status;
|
||||
private String type;
|
||||
private String imageUrl;
|
||||
private int totalEpisodes;
|
||||
|
||||
|
||||
// Getters y Setters
|
||||
public int getId() { return id; }
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) { this.id = id; }
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getUserId() { return userId; }
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) { this.userId = userId; }
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public int getScore() { return score; }
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(int score) { this.score = score; }
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public int getProgress() { return progress; }
|
||||
public int getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) { this.progress = progress; }
|
||||
public void setProgress(int progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public String getStatus() { return status; }
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getType() { return type; }
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) { this.type = type; }
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getImageUrl() { return imageUrl; }
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public int getTotalEpisodes() {
|
||||
return totalEpisodes;
|
||||
}
|
||||
|
||||
public void setTotalEpisodes(int totalEpisodes) {
|
||||
this.totalEpisodes = totalEpisodes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,37 +15,79 @@ public class MangaEntity implements Serializable {
|
|||
private String status;
|
||||
private String type;
|
||||
private String imageUrl;
|
||||
private int totalChapters;
|
||||
|
||||
// Getters y Setters
|
||||
public int getId() { return id; }
|
||||
|
||||
public void setId(int id) { this.id = id; }
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getUserId() { return userId; }
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) { this.userId = userId; }
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public int getScore() { return score; }
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setScore(int score) { this.score = score; }
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public int getProgress() { return progress; }
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) { this.progress = progress; }
|
||||
public int getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public String getStatus() { return status; }
|
||||
public void setProgress(int progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public void setType(String type) { this.type = type; }
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getImageUrl() { return imageUrl; }
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public int getTotalChapters() {
|
||||
return totalChapters;
|
||||
}
|
||||
|
||||
public void setTotalChapters(int totalChapters) {
|
||||
this.totalChapters = totalChapters;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,47 @@
|
|||
package com.santiparra.yomitrack.db.entities;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Entidad que representa un usuario en la base de datos
|
||||
* Entidad que representa un usuario.
|
||||
*/
|
||||
public class UserEntity {
|
||||
public int id;
|
||||
public String username;
|
||||
public String password;
|
||||
|
||||
@SerializedName("id")
|
||||
private int id;
|
||||
|
||||
@SerializedName("username")
|
||||
private String username;
|
||||
|
||||
@SerializedName("password")
|
||||
private String password;
|
||||
|
||||
public UserEntity(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
public class AniListAnime {
|
||||
private int id;
|
||||
private String title;
|
||||
private String imageUrl;
|
||||
|
||||
// Constructor vacío
|
||||
public AniListAnime() {}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,9 +1,31 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.santiparra.yomitrack.db.entities.UserEntity;
|
||||
|
||||
/**
|
||||
* Respuesta del servidor al intentar iniciar sesión.
|
||||
*/
|
||||
public class LoginResponse {
|
||||
public boolean success;
|
||||
public String message;
|
||||
public UserEntity user;
|
||||
|
||||
@SerializedName("success")
|
||||
private boolean success;
|
||||
|
||||
@SerializedName("message")
|
||||
private String message;
|
||||
|
||||
@SerializedName("user")
|
||||
private UserEntity user;
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,27 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class RegisterResponse {
|
||||
|
||||
@SerializedName("success")
|
||||
private boolean success;
|
||||
|
||||
@SerializedName("message")
|
||||
private String message;
|
||||
|
||||
@SerializedName("userId")
|
||||
private int userId;
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
/**
|
||||
* Representa una estadística del usuario, usada para barras de progreso.
|
||||
* Incluye categoría, cantidad y porcentaje de completado.
|
||||
*/
|
||||
public class UserStats {
|
||||
private String category;
|
||||
private int count;
|
||||
private int percentage;
|
||||
|
||||
public UserStats(String category, int count, int percentage) {
|
||||
this.category = category;
|
||||
this.count = count;
|
||||
this.percentage = percentage;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getPercentage() {
|
||||
return percentage;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,18 +29,10 @@ public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHol
|
|||
private final OnAnimeClickListener onEditClick;
|
||||
private final OnAnimeClickListener onLongClick;
|
||||
|
||||
// ✅ Constructor optimizado para uso simple
|
||||
public AnimeAdapter(Context context) {
|
||||
this.animeList = new ArrayList<>();
|
||||
this.viewType = VIEW_NORMAL;
|
||||
this.onEditClick = null;
|
||||
this.onLongClick = null;
|
||||
}
|
||||
|
||||
public AnimeAdapter(List<AnimeEntity> animeList, int viewType,
|
||||
OnAnimeClickListener onEditClick,
|
||||
OnAnimeClickListener onLongClick) {
|
||||
this.animeList = animeList;
|
||||
this.animeList = animeList != null ? animeList : new ArrayList<>();
|
||||
this.viewType = viewType;
|
||||
this.onEditClick = onEditClick;
|
||||
this.onLongClick = onLongClick;
|
||||
|
|
@ -51,6 +43,11 @@ public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHol
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void updateList(List<AnimeEntity> newList) {
|
||||
this.animeList = newList != null ? newList : new ArrayList<>();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
|
|
@ -165,14 +162,7 @@ public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHol
|
|||
}
|
||||
}
|
||||
|
||||
public void updateList(List<AnimeEntity> newList) {
|
||||
this.animeList = newList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
public interface OnAnimeClickListener {
|
||||
void onClick(AnimeEntity anime);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,25 +11,25 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.model.AniListAnime;
|
||||
import com.santiparra.yomitrack.model.AniListMedia;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AnimeSearchAdapter extends RecyclerView.Adapter<AnimeSearchAdapter.SearchViewHolder> {
|
||||
|
||||
private List<AniListAnime> animeList;
|
||||
private List<AniListMedia> animeList;
|
||||
private final OnAnimeClickListener clickListener;
|
||||
|
||||
public interface OnAnimeClickListener {
|
||||
void onClick(AniListAnime anime);
|
||||
void onClick(AniListMedia anime);
|
||||
}
|
||||
|
||||
public AnimeSearchAdapter(List<AniListAnime> animeList, OnAnimeClickListener clickListener) {
|
||||
public AnimeSearchAdapter(List<AniListMedia> animeList, OnAnimeClickListener clickListener) {
|
||||
this.animeList = animeList;
|
||||
this.clickListener = clickListener;
|
||||
}
|
||||
|
||||
public void setAnimeList(List<AniListAnime> animeList) {
|
||||
public void setAnimeList(List<AniListMedia> animeList) {
|
||||
this.animeList = animeList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ public class AnimeSearchAdapter extends RecyclerView.Adapter<AnimeSearchAdapter.
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SearchViewHolder holder, int position) {
|
||||
AniListAnime anime = animeList.get(position);
|
||||
AniListMedia anime = animeList.get(position);
|
||||
holder.title.setText(anime.getTitle());
|
||||
|
||||
Glide.with(holder.itemView.getContext())
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// MangaAdapter.java actualizado con statusDot dinámico
|
||||
|
||||
package com.santiparra.yomitrack.model.adapters.manga_adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -38,11 +37,6 @@ public class MangaAdapter extends RecyclerView.Adapter<MangaAdapter.MangaViewHol
|
|||
this.onLongClick = onLongClick;
|
||||
}
|
||||
|
||||
public void setViewType(int viewType) {
|
||||
this.viewType = viewType;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MangaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
|
|
@ -71,7 +65,8 @@ public class MangaAdapter extends RecyclerView.Adapter<MangaAdapter.MangaViewHol
|
|||
}
|
||||
|
||||
if (holder.textProgress != null) {
|
||||
holder.textProgress.setText(manga.getProgress() + " caps");
|
||||
String progress = manga.getProgress() + " caps";
|
||||
holder.textProgress.setText(progress);
|
||||
}
|
||||
|
||||
if (holder.textScore != null) {
|
||||
|
|
@ -97,7 +92,7 @@ public class MangaAdapter extends RecyclerView.Adapter<MangaAdapter.MangaViewHol
|
|||
case "Completed":
|
||||
colorResId = R.color.status_completed;
|
||||
break;
|
||||
case "Reading":
|
||||
case "Watching":
|
||||
colorResId = R.color.status_watching;
|
||||
break;
|
||||
case "Paused":
|
||||
|
|
@ -156,6 +151,11 @@ public class MangaAdapter extends RecyclerView.Adapter<MangaAdapter.MangaViewHol
|
|||
}
|
||||
}
|
||||
|
||||
public void updateList(List<MangaEntity> newList) {
|
||||
this.mangaList = newList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public interface OnMangaClickListener {
|
||||
void onClick(MangaEntity manga);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,25 +11,25 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.model.AniListAnime;
|
||||
import com.santiparra.yomitrack.model.AniListMedia;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MangaSearchAdapter extends RecyclerView.Adapter<MangaSearchAdapter.SearchViewHolder> {
|
||||
|
||||
private List<AniListAnime> mangaList;
|
||||
private List<AniListMedia> mangaList;
|
||||
private final OnMangaClickListener clickListener;
|
||||
|
||||
public interface OnMangaClickListener {
|
||||
void onClick(AniListAnime manga);
|
||||
void onClick(AniListMedia manga);
|
||||
}
|
||||
|
||||
public MangaSearchAdapter(List<AniListAnime> mangaList, OnMangaClickListener clickListener) {
|
||||
public MangaSearchAdapter(List<AniListMedia> mangaList, OnMangaClickListener clickListener) {
|
||||
this.mangaList = mangaList;
|
||||
this.clickListener = clickListener;
|
||||
}
|
||||
|
||||
public void setMangaList(List<AniListAnime> mangaList) {
|
||||
public void setMangaList(List<AniListMedia> mangaList) {
|
||||
this.mangaList = mangaList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ public class MangaSearchAdapter extends RecyclerView.Adapter<MangaSearchAdapter.
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SearchViewHolder holder, int position) {
|
||||
AniListAnime manga = mangaList.get(position);
|
||||
AniListMedia manga = mangaList.get(position);
|
||||
holder.title.setText(manga.getTitle());
|
||||
|
||||
Glide.with(holder.itemView.getContext())
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// AddAnimeFragment.java actualizado con LinearLayoutManager asignado al RecyclerView
|
||||
// AddAnimeFragment.java
|
||||
|
||||
package com.santiparra.yomitrack.ui.fragments.addanime;
|
||||
|
||||
|
|
@ -26,11 +26,13 @@ import com.santiparra.yomitrack.R;
|
|||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||
import com.santiparra.yomitrack.model.AniListAnime;
|
||||
import com.santiparra.yomitrack.model.AniListMedia;
|
||||
import com.santiparra.yomitrack.model.adapters.anime_adapter.AnimeSearchAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
|
@ -92,9 +94,9 @@ public class AddAnimeFragment extends Fragment {
|
|||
(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
|
||||
String query = searchEditText.getText().toString().trim();
|
||||
if (!query.isEmpty()) {
|
||||
api.searchAnimeAniList(query).enqueue(new Callback<List<AniListAnime>>() {
|
||||
api.searchAniList(query, "ANIME").enqueue(new Callback<List<AniListMedia>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<AniListAnime>> call, Response<List<AniListAnime>> response) {
|
||||
public void onResponse(Call<List<AniListMedia>> call, Response<List<AniListMedia>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
searchAdapter.setAnimeList(response.body());
|
||||
} else {
|
||||
|
|
@ -103,7 +105,7 @@ public class AddAnimeFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<AniListAnime>> call, Throwable t) {
|
||||
public void onFailure(Call<List<AniListMedia>> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error de red", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
|
@ -114,7 +116,7 @@ public class AddAnimeFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
private void onAnimeSelected(AniListAnime selected) {
|
||||
private void onAnimeSelected(AniListMedia selected) {
|
||||
String status = statusSpinner.getSelectedItem().toString();
|
||||
String type = typeSpinner.getSelectedItem().toString();
|
||||
|
||||
|
|
@ -139,6 +141,7 @@ public class AddAnimeFragment extends Fragment {
|
|||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Anime añadido", Toast.LENGTH_SHORT).show();
|
||||
registrarActividad(anime.getTitle());
|
||||
requireActivity().getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al guardar anime", Toast.LENGTH_SHORT).show();
|
||||
|
|
@ -151,4 +154,18 @@ public class AddAnimeFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void registrarActividad(String titulo) {
|
||||
Map<String, Object> actividad = new HashMap<>();
|
||||
actividad.put("userId", userId);
|
||||
actividad.put("action", "Añadió");
|
||||
actividad.put("mediaTitle", titulo);
|
||||
|
||||
api.postActivity(actividad).enqueue(new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {}
|
||||
@Override
|
||||
public void onFailure(Call call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import com.santiparra.yomitrack.R;
|
|||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||
import com.santiparra.yomitrack.model.AniListAnime;
|
||||
import com.santiparra.yomitrack.model.AniListMedia;
|
||||
import com.santiparra.yomitrack.model.adapters.manga_adapter.MangaSearchAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
|
@ -46,7 +48,7 @@ public class AddMangaFragment extends Fragment {
|
|||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_add_anime, container, false);
|
||||
View view = inflater.inflate(R.layout.fragment_add_manga, container, false);
|
||||
|
||||
searchEditText = view.findViewById(R.id.editTextSearch);
|
||||
scoreEditText = view.findViewById(R.id.editTextScore);
|
||||
|
|
@ -69,12 +71,12 @@ public class AddMangaFragment extends Fragment {
|
|||
|
||||
private void setupSpinners() {
|
||||
ArrayAdapter<CharSequence> statusAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.anime_status_array, android.R.layout.simple_spinner_item);
|
||||
requireContext(), R.array.manga_status_array, android.R.layout.simple_spinner_item);
|
||||
statusAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
statusSpinner.setAdapter(statusAdapter);
|
||||
|
||||
ArrayAdapter<CharSequence> typeAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.anime_type_array, android.R.layout.simple_spinner_item);
|
||||
requireContext(), R.array.manga_type_array, android.R.layout.simple_spinner_item);
|
||||
typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
typeSpinner.setAdapter(typeAdapter);
|
||||
}
|
||||
|
|
@ -90,9 +92,9 @@ public class AddMangaFragment extends Fragment {
|
|||
(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
|
||||
String query = searchEditText.getText().toString().trim();
|
||||
if (!query.isEmpty()) {
|
||||
api.searchMangaAniList(query).enqueue(new Callback<List<AniListAnime>>() {
|
||||
api.searchAniList(query, "MANGA").enqueue(new Callback<List<AniListMedia>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<AniListAnime>> call, Response<List<AniListAnime>> response) {
|
||||
public void onResponse(Call<List<AniListMedia>> call, Response<List<AniListMedia>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
searchAdapter.setMangaList(response.body());
|
||||
} else {
|
||||
|
|
@ -101,7 +103,7 @@ public class AddMangaFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<AniListAnime>> call, Throwable t) {
|
||||
public void onFailure(Call<List<AniListMedia>> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error de red", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
|
@ -112,7 +114,7 @@ public class AddMangaFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
private void onMangaSelected(AniListAnime selected) {
|
||||
private void onMangaSelected(AniListMedia selected) {
|
||||
String status = statusSpinner.getSelectedItem().toString();
|
||||
String type = typeSpinner.getSelectedItem().toString();
|
||||
|
||||
|
|
@ -136,7 +138,8 @@ public class AddMangaFragment extends Fragment {
|
|||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Manga añadido", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), "Manga añadido correctamente", Toast.LENGTH_SHORT).show();
|
||||
registrarActividad(manga.getTitle());
|
||||
requireActivity().getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al guardar manga", Toast.LENGTH_SHORT).show();
|
||||
|
|
@ -149,4 +152,18 @@ public class AddMangaFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void registrarActividad(String titulo) {
|
||||
Map<String, Object> actividad = new HashMap<>();
|
||||
actividad.put("userId", userId);
|
||||
actividad.put("action", "Añadió");
|
||||
actividad.put("mediaTitle", titulo);
|
||||
|
||||
api.postActivity(actividad).enqueue(new Callback<>() {
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {}
|
||||
@Override
|
||||
public void onFailure(Call call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
|
@ -24,6 +26,7 @@ import com.santiparra.yomitrack.R;
|
|||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||
import com.santiparra.yomitrack.model.AnimePageResponse;
|
||||
import com.santiparra.yomitrack.model.adapters.anime_adapter.AnimeAdapter;
|
||||
import com.santiparra.yomitrack.ui.fragments.addanime.AddAnimeFragment;
|
||||
import com.santiparra.yomitrack.ui.fragments.editanime.EditAnimeFragment;
|
||||
|
|
@ -45,7 +48,11 @@ public class FragmentAnime extends Fragment {
|
|||
|
||||
private ImageButton btnViewCompact, btnViewNormal, btnViewLarge;
|
||||
private int currentViewType = AnimeAdapter.VIEW_NORMAL;
|
||||
private List<AnimeEntity> animeList = new ArrayList<>();
|
||||
private final List<AnimeEntity> animeList = new ArrayList<>();
|
||||
|
||||
private boolean isLoading = false;
|
||||
private int currentPage = 1;
|
||||
private final int PAGE_SIZE = 20;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
|
@ -68,26 +75,25 @@ public class FragmentAnime extends Fragment {
|
|||
|
||||
editSearch = view.findViewById(R.id.editSearch);
|
||||
editSearch.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
filterAnimeList(s.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
@Override public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("current_user_id", -1);
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("user_id", -1);
|
||||
|
||||
// Botones de vista
|
||||
btnViewCompact.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_COMPACT));
|
||||
btnViewNormal.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_NORMAL));
|
||||
btnViewLarge.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_LARGE));
|
||||
if (userId == -1) {
|
||||
Toast.makeText(getContext(), "Error: sesión no iniciada", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
adapter = new AnimeAdapter(animeList, currentViewType, this::showEditDialog, this::deleteAnime);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
fabAdd.setOnClickListener(v -> requireActivity().getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
|
|
@ -95,7 +101,39 @@ public class FragmentAnime extends Fragment {
|
|||
.addToBackStack(null)
|
||||
.commit());
|
||||
|
||||
fetchAnimeList();
|
||||
btnViewCompact.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_COMPACT));
|
||||
btnViewNormal.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_NORMAL));
|
||||
btnViewLarge.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_LARGE));
|
||||
|
||||
setViewType(currentViewType);
|
||||
loadMoreAnimes(currentPage);
|
||||
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (layoutManager == null) return;
|
||||
|
||||
int visibleItemCount = layoutManager.getChildCount();
|
||||
int totalItemCount = layoutManager.getItemCount();
|
||||
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if (!isLoading && (firstVisibleItemPosition + visibleItemCount) >= totalItemCount - 4) {
|
||||
currentPage++;
|
||||
loadMoreAnimes(currentPage);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> {
|
||||
int bottomInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
|
||||
recyclerView.setPadding(
|
||||
recyclerView.getPaddingLeft(),
|
||||
recyclerView.getPaddingTop(),
|
||||
recyclerView.getPaddingRight(),
|
||||
bottomInset + 95
|
||||
);
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
||||
private void filterAnimeList(String query) {
|
||||
|
|
@ -108,33 +146,13 @@ public class FragmentAnime extends Fragment {
|
|||
adapter.updateList(filtered);
|
||||
}
|
||||
|
||||
private void fetchAnimeList() {
|
||||
api.getAnimeByUser(userId).enqueue(new Callback<List<AnimeEntity>>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<List<AnimeEntity>> call,
|
||||
@NonNull Response<List<AnimeEntity>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
animeList = response.body();
|
||||
setViewType(currentViewType);
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al cargar animes", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<AnimeEntity>> call, @NonNull Throwable t) {
|
||||
Toast.makeText(getContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setViewType(int viewType) {
|
||||
currentViewType = viewType;
|
||||
|
||||
if (viewType == AnimeAdapter.VIEW_LARGE) {
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2));
|
||||
} else {
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
}
|
||||
|
||||
adapter = new AnimeAdapter(animeList, viewType,
|
||||
|
|
@ -155,17 +173,52 @@ public class FragmentAnime extends Fragment {
|
|||
api.deleteAnime(anime.getId()).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (!isAdded()) return;
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Anime eliminado", Toast.LENGTH_SHORT).show();
|
||||
fetchAnimeList();
|
||||
Toast.makeText(requireContext(), "Anime eliminado", Toast.LENGTH_SHORT).show();
|
||||
currentPage = 1;
|
||||
animeList.clear();
|
||||
loadMoreAnimes(currentPage);
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||
if (isAdded()) {
|
||||
Toast.makeText(requireContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMoreAnimes(int page) {
|
||||
isLoading = true;
|
||||
|
||||
api.getAnimes(userId, page, PAGE_SIZE).enqueue(new Callback<AnimePageResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<AnimePageResponse> call, Response<AnimePageResponse> response) {
|
||||
if (!isAdded()) return;
|
||||
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
List<AnimeEntity> nuevos = response.body().getData();
|
||||
animeList.addAll(nuevos);
|
||||
adapter.notifyItemRangeInserted(animeList.size() - nuevos.size(), nuevos.size());
|
||||
|
||||
isLoading = response.body().isHasNextPage();
|
||||
} else {
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<AnimePageResponse> call, Throwable t) {
|
||||
isLoading = false;
|
||||
if (isAdded()) {
|
||||
Toast.makeText(requireContext(), "Error al cargar más animes", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,12 @@
|
|||
// EditAnimeFragment.java optimizado con setupSpinners y safe saveChanges
|
||||
|
||||
package com.santiparra.yomitrack.ui.fragments.editanime;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -31,19 +25,24 @@ public class EditAnimeFragment extends Fragment {
|
|||
|
||||
private EditText editTextTitle, editTextScore, editTextProgress;
|
||||
private Spinner spinnerStatus, spinnerType;
|
||||
private Button buttonSave;
|
||||
private Button buttonSave, buttonDelete;
|
||||
private AnimeEntity anime;
|
||||
private ApiService api;
|
||||
private int userId;
|
||||
|
||||
public EditAnimeFragment(AnimeEntity anime) {
|
||||
this.anime = anime;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_edit_anime, container, false);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_edit_anime, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
editTextTitle = view.findViewById(R.id.editTextAnimeTitle);
|
||||
editTextScore = view.findViewById(R.id.editTextScore);
|
||||
|
|
@ -51,51 +50,47 @@ public class EditAnimeFragment extends Fragment {
|
|||
spinnerStatus = view.findViewById(R.id.spinnerStatus);
|
||||
spinnerType = view.findViewById(R.id.spinnerType);
|
||||
buttonSave = view.findViewById(R.id.buttonSaveAnime);
|
||||
buttonDelete = view.findViewById(R.id.buttonDeleteAnime);
|
||||
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("current_user_id", -1);
|
||||
|
||||
if (getArguments() != null && getArguments().containsKey("anime")) {
|
||||
anime = (AnimeEntity) getArguments().getSerializable("anime");
|
||||
fillFields();
|
||||
// Llenar campos
|
||||
fillFields();
|
||||
|
||||
// Spinner datos
|
||||
String[] statusArray = getResources().getStringArray(R.array.anime_status_array);
|
||||
String[] typeArray = getResources().getStringArray(R.array.anime_type_array);
|
||||
|
||||
ArrayAdapter<String> statusAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statusArray);
|
||||
spinnerStatus.setAdapter(statusAdapter);
|
||||
|
||||
ArrayAdapter<String> typeAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, typeArray);
|
||||
spinnerType.setAdapter(typeAdapter);
|
||||
|
||||
for (int i = 0; i < statusArray.length; i++) {
|
||||
if (statusArray[i].equalsIgnoreCase(anime.getStatus())) {
|
||||
spinnerStatus.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setupSpinners();
|
||||
for (int i = 0; i < typeArray.length; i++) {
|
||||
if (typeArray[i].equalsIgnoreCase(anime.getType())) {
|
||||
spinnerType.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buttonSave.setOnClickListener(v -> saveChanges());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setupSpinners() {
|
||||
ArrayAdapter<CharSequence> statusAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.anime_status_array, android.R.layout.simple_spinner_item);
|
||||
statusAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerStatus.setAdapter(statusAdapter);
|
||||
|
||||
ArrayAdapter<CharSequence> typeAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.anime_type_array, android.R.layout.simple_spinner_item);
|
||||
typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerType.setAdapter(typeAdapter);
|
||||
|
||||
if (anime != null) {
|
||||
String[] statusArray = getResources().getStringArray(R.array.anime_status_array);
|
||||
String[] typeArray = getResources().getStringArray(R.array.anime_type_array);
|
||||
|
||||
for (int i = 0; i < statusArray.length; i++) {
|
||||
if (statusArray[i].equalsIgnoreCase(anime.getStatus())) {
|
||||
spinnerStatus.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < typeArray.length; i++) {
|
||||
if (typeArray[i].equalsIgnoreCase(anime.getType())) {
|
||||
spinnerType.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
buttonDelete.setOnClickListener(v -> {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Eliminar anime")
|
||||
.setMessage("¿Estás seguro de que quieres eliminar este anime?")
|
||||
.setPositiveButton("Sí", (dialog, which) -> deleteAnime())
|
||||
.setNegativeButton("Cancelar", null)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void fillFields() {
|
||||
|
|
@ -128,13 +123,8 @@ public class EditAnimeFragment extends Fragment {
|
|||
return;
|
||||
}
|
||||
|
||||
String status = spinnerStatus.getSelectedItem() != null ? spinnerStatus.getSelectedItem().toString() : "";
|
||||
String type = spinnerType.getSelectedItem() != null ? spinnerType.getSelectedItem().toString() : "";
|
||||
|
||||
if (status.isEmpty() || type.isEmpty()) {
|
||||
Toast.makeText(requireContext(), "Debe seleccionar estado y tipo", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
String status = spinnerStatus.getSelectedItem().toString();
|
||||
String type = spinnerType.getSelectedItem().toString();
|
||||
|
||||
anime.setTitle(title);
|
||||
anime.setScore(score);
|
||||
|
|
@ -142,11 +132,13 @@ public class EditAnimeFragment extends Fragment {
|
|||
anime.setStatus(status);
|
||||
anime.setType(type);
|
||||
|
||||
api.updateAnime(anime.getId(),anime).enqueue(new Callback<String>() {
|
||||
api.updateAnime(anime.getId(), anime).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(requireContext(), "Anime actualizado", Toast.LENGTH_SHORT).show();
|
||||
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE)
|
||||
.edit().putBoolean("refresh_profile", true).apply();
|
||||
requireActivity().getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Error al actualizar", Toast.LENGTH_SHORT).show();
|
||||
|
|
@ -159,4 +151,25 @@ public class EditAnimeFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void deleteAnime() {
|
||||
api.deleteAnime(anime.getId()).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(requireContext(), "Anime eliminado", Toast.LENGTH_SHORT).show();
|
||||
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE)
|
||||
.edit().putBoolean("refresh_profile", true).apply();
|
||||
requireActivity().getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,12 @@
|
|||
// EditMangaFragment.java conectado a fragment_edit_manga.xml y funcional
|
||||
|
||||
package com.santiparra.yomitrack.ui.fragments.editmanga;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -31,20 +25,24 @@ public class EditMangaFragment extends Fragment {
|
|||
|
||||
private EditText editTextTitle, editTextScore, editTextProgress;
|
||||
private Spinner spinnerStatus, spinnerType;
|
||||
private Button buttonSave;
|
||||
private Button buttonSave, buttonDelete;
|
||||
private MangaEntity manga;
|
||||
private ApiService api;
|
||||
private int userId;
|
||||
|
||||
public EditMangaFragment(MangaEntity manga) {
|
||||
this.manga = manga;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_edit_manga, container, false);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_edit_manga, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
editTextTitle = view.findViewById(R.id.editTextMangaTitle);
|
||||
editTextScore = view.findViewById(R.id.editTextScore);
|
||||
|
|
@ -52,41 +50,21 @@ public class EditMangaFragment extends Fragment {
|
|||
spinnerStatus = view.findViewById(R.id.spinnerStatus);
|
||||
spinnerType = view.findViewById(R.id.spinnerType);
|
||||
buttonSave = view.findViewById(R.id.buttonSaveManga);
|
||||
buttonDelete = view.findViewById(R.id.buttonDeleteManga);
|
||||
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("current_user_id", -1);
|
||||
|
||||
setupSpinners();
|
||||
fillFields();
|
||||
|
||||
if (getArguments() != null && getArguments().containsKey("manga")) {
|
||||
manga = (MangaEntity) getArguments().getSerializable("manga");
|
||||
fillFields();
|
||||
}
|
||||
String[] statusArray = getResources().getStringArray(R.array.manga_status_array);
|
||||
String[] typeArray = getResources().getStringArray(R.array.manga_type_array);
|
||||
|
||||
buttonSave.setOnClickListener(v -> updateManga());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setupSpinners() {
|
||||
ArrayAdapter<CharSequence> statusAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.anime_status_array, android.R.layout.simple_spinner_item);
|
||||
statusAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
ArrayAdapter<String> statusAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statusArray);
|
||||
spinnerStatus.setAdapter(statusAdapter);
|
||||
|
||||
ArrayAdapter<CharSequence> typeAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.anime_type_array, android.R.layout.simple_spinner_item);
|
||||
typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
ArrayAdapter<String> typeAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, typeArray);
|
||||
spinnerType.setAdapter(typeAdapter);
|
||||
}
|
||||
|
||||
private void fillFields() {
|
||||
editTextTitle.setText(manga.getTitle());
|
||||
editTextScore.setText(String.valueOf(manga.getScore()));
|
||||
editTextProgress.setText(String.valueOf(manga.getProgress()));
|
||||
|
||||
String[] statusArray = getResources().getStringArray(R.array.anime_status_array);
|
||||
for (int i = 0; i < statusArray.length; i++) {
|
||||
if (statusArray[i].equalsIgnoreCase(manga.getStatus())) {
|
||||
spinnerStatus.setSelection(i);
|
||||
|
|
@ -94,19 +72,55 @@ public class EditMangaFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
String[] typeArray = getResources().getStringArray(R.array.anime_type_array);
|
||||
for (int i = 0; i < typeArray.length; i++) {
|
||||
if (typeArray[i].equalsIgnoreCase(manga.getType())) {
|
||||
spinnerType.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buttonSave.setOnClickListener(v -> saveChanges());
|
||||
|
||||
buttonDelete.setOnClickListener(v -> {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Eliminar manga")
|
||||
.setMessage("¿Estás seguro de que quieres eliminar este manga?")
|
||||
.setPositiveButton("Sí", (dialog, which) -> deleteManga())
|
||||
.setNegativeButton("Cancelar", null)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateManga() {
|
||||
private void fillFields() {
|
||||
editTextTitle.setText(manga.getTitle());
|
||||
editTextScore.setText(String.valueOf(manga.getScore()));
|
||||
editTextProgress.setText(String.valueOf(manga.getProgress()));
|
||||
}
|
||||
|
||||
private void saveChanges() {
|
||||
if (manga == null) {
|
||||
Toast.makeText(requireContext(), "Error: Manga no cargado", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
String title = editTextTitle.getText().toString().trim();
|
||||
int score = Integer.parseInt(editTextScore.getText().toString());
|
||||
int progress = Integer.parseInt(editTextProgress.getText().toString());
|
||||
String scoreStr = editTextScore.getText().toString().trim();
|
||||
String progressStr = editTextProgress.getText().toString().trim();
|
||||
|
||||
if (title.isEmpty()) {
|
||||
Toast.makeText(requireContext(), "El título no puede estar vacío", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
int score = 0, progress = 0;
|
||||
try {
|
||||
score = Integer.parseInt(scoreStr);
|
||||
progress = Integer.parseInt(progressStr);
|
||||
} catch (NumberFormatException e) {
|
||||
Toast.makeText(requireContext(), "Score y Progreso deben ser números", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
String status = spinnerStatus.getSelectedItem().toString();
|
||||
String type = spinnerType.getSelectedItem().toString();
|
||||
|
||||
|
|
@ -116,20 +130,43 @@ public class EditMangaFragment extends Fragment {
|
|||
manga.setStatus(status);
|
||||
manga.setType(type);
|
||||
|
||||
api.updateManga(manga.getId(),manga).enqueue(new Callback<String>() {
|
||||
api.updateManga(manga.getId(), manga).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Manga actualizado", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), "Manga actualizado", Toast.LENGTH_SHORT).show();
|
||||
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE)
|
||||
.edit().putBoolean("refresh_profile", true).apply();
|
||||
requireActivity().getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al actualizar", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), "Error al actualizar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void deleteManga() {
|
||||
api.deleteManga(manga.getId()).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(requireContext(), "Manga eliminado", Toast.LENGTH_SHORT).show();
|
||||
requireContext().getSharedPreferences("user_profile", Context.MODE_PRIVATE)
|
||||
.edit().putBoolean("refresh_profile", true).apply();
|
||||
requireActivity().getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
Toast.makeText(requireContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ public class LoginActivity extends AppCompatActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login); // contiene el NavHostFragment
|
||||
setContentView(R.layout.activity_login);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.databinding.FragmentLoginBinding;
|
||||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.db.entities.UserEntity;
|
||||
|
|
@ -26,86 +27,85 @@ import retrofit2.Call;
|
|||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* Fragmento que gestiona el inicio de sesión y entrada como invitado.
|
||||
*/
|
||||
public class LoginFragment extends Fragment {
|
||||
|
||||
private EditText usernameEditText, passwordEditText;
|
||||
private Button loginButton, guestButton, registerButton;
|
||||
private FragmentLoginBinding binding;
|
||||
|
||||
public LoginFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_login, container, false);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
binding = FragmentLoginBinding.inflate(inflater, container, false);
|
||||
|
||||
usernameEditText = view.findViewById(R.id.editTextUsername);
|
||||
passwordEditText = view.findViewById(R.id.editTextPassword);
|
||||
loginButton = view.findViewById(R.id.buttonLogin);
|
||||
guestButton = view.findViewById(R.id.buttonGuest);
|
||||
registerButton = view.findViewById(R.id.buttonGoRegister);
|
||||
binding.buttonLogin.setOnClickListener(v -> loginUser());
|
||||
binding.buttonGuest.setOnClickListener(v -> loginAsGuest());
|
||||
binding.buttonGoRegister.setOnClickListener(v -> {
|
||||
NavController navController = NavHostFragment.findNavController(LoginFragment.this);
|
||||
navController.navigate(R.id.action_loginFragment_to_registerFragment);
|
||||
});
|
||||
|
||||
loginButton.setOnClickListener(v -> {
|
||||
String username = usernameEditText.getText().toString().trim();
|
||||
String password = passwordEditText.getText().toString().trim();
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
if (username.isEmpty() || password.isEmpty()) {
|
||||
Toast.makeText(getContext(), "Rellena todos los campos", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
private void loginUser() {
|
||||
String username = binding.editTextUsername.getText().toString().trim();
|
||||
String password = binding.editTextPassword.getText().toString().trim();
|
||||
|
||||
if (username.isEmpty() || password.isEmpty()) {
|
||||
showToast("Ingrese usuario y contraseña");
|
||||
return;
|
||||
}
|
||||
|
||||
UserEntity user = new UserEntity(username, password);
|
||||
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
apiService.loginUser(user).enqueue(new Callback<LoginResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isSuccess()) {
|
||||
saveUserSession(response.body().getUser().getId(), response.body().getUser().getUsername());
|
||||
showToast("Inicio de sesión exitoso");
|
||||
goToMainActivity();
|
||||
} else {
|
||||
showToast("Credenciales incorrectas");
|
||||
}
|
||||
}
|
||||
|
||||
ApiService api = ApiClient.getClient().create(ApiService.class);
|
||||
UserEntity user = new UserEntity();
|
||||
user.username = username;
|
||||
user.password = password;
|
||||
|
||||
Call<LoginResponse> call = api.loginUser(user);
|
||||
call.enqueue(new Callback<LoginResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
LoginResponse result = response.body();
|
||||
|
||||
if (result.success) {
|
||||
UserEntity user = result.user;
|
||||
Toast.makeText(getContext(), "Bienvenido " + user.username, Toast.LENGTH_SHORT).show();
|
||||
|
||||
saveSession(user.id); // ✅ Guardamos el ID del usuario
|
||||
navigateToHome(); // ✅ Entramos a MainActivity
|
||||
} else {
|
||||
Toast.makeText(getContext(), result.message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error inesperado", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<LoginResponse> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error de red: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<LoginResponse> call, @NonNull Throwable t) {
|
||||
showToast("Error de red: " + t.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
guestButton.setOnClickListener(v -> {
|
||||
saveSession(-1); // usuario invitado
|
||||
navigateToHome();
|
||||
});
|
||||
|
||||
registerButton.setOnClickListener(v -> {
|
||||
NavController navController = NavHostFragment.findNavController(LoginFragment.this);
|
||||
navController.navigate(R.id.action_login_to_register);
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void saveSession(int userId) {
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
prefs.edit().putInt("current_user_id", userId).apply();
|
||||
private void loginAsGuest() {
|
||||
saveUserSession(-1, "Invitado");
|
||||
goToMainActivity();
|
||||
}
|
||||
|
||||
private void navigateToHome() {
|
||||
private void saveUserSession(int userId, String username) {
|
||||
SharedPreferences prefs = requireActivity().getSharedPreferences("user_session", Context.MODE_PRIVATE);
|
||||
prefs.edit()
|
||||
.putInt("user_id", userId)
|
||||
.putString("username", username)
|
||||
.apply();
|
||||
}
|
||||
|
||||
private void goToMainActivity() {
|
||||
startActivity(new Intent(getActivity(), MainActivity.class));
|
||||
requireActivity().finish();
|
||||
}
|
||||
|
||||
private void showToast(String message) {
|
||||
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,23 @@
|
|||
package com.santiparra.yomitrack.ui.fragments.manga_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
|
@ -18,10 +26,12 @@ import com.santiparra.yomitrack.R;
|
|||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||
import com.santiparra.yomitrack.model.MangaPageResponse;
|
||||
import com.santiparra.yomitrack.model.adapters.manga_adapter.MangaAdapter;
|
||||
import com.santiparra.yomitrack.ui.fragments.addmanga.AddMangaFragment;
|
||||
import com.santiparra.yomitrack.ui.fragments.editmanga.EditMangaFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
|
|
@ -30,29 +40,57 @@ import retrofit2.Response;
|
|||
|
||||
public class FragmentManga extends Fragment {
|
||||
|
||||
private EditText editSearch;
|
||||
private RecyclerView recyclerView;
|
||||
private MangaAdapter adapter;
|
||||
private ApiService api;
|
||||
private int userId = 1;
|
||||
|
||||
private ImageButton btnViewCompact, btnViewNormal, btnViewLarge;
|
||||
private int currentViewType = MangaAdapter.VIEW_NORMAL;
|
||||
private int userId = 1; // Deberías usar SharedPreferences si tienes login
|
||||
private List<MangaEntity> mangaList = new ArrayList<>();
|
||||
|
||||
private boolean isLoading = false;
|
||||
private int currentPage = 1;
|
||||
private final int PAGE_SIZE = 20;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_mlist, container, false);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_mlist, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
recyclerView = view.findViewById(R.id.recyclerViewManga);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
||||
ImageView changeViewButton = view.findViewById(R.id.buttonChangeViewType);
|
||||
btnViewCompact = view.findViewById(R.id.btnViewCompact);
|
||||
btnViewNormal = view.findViewById(R.id.btnViewNormal);
|
||||
btnViewLarge = view.findViewById(R.id.btnViewLarge);
|
||||
FloatingActionButton fabAdd = view.findViewById(R.id.fabAddManga);
|
||||
editSearch = view.findViewById(R.id.editSearch);
|
||||
|
||||
editSearch.addTextChangedListener(new TextWatcher() {
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override public void afterTextChanged(Editable s) {}
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
filterMangaList(s.toString());
|
||||
}
|
||||
});
|
||||
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("user_id", -1);
|
||||
|
||||
if (userId == -1) {
|
||||
Toast.makeText(getContext(), "Error: sesión no iniciada", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
changeViewButton.setOnClickListener(v -> {
|
||||
currentViewType = (currentViewType + 1) % 3;
|
||||
if (adapter != null) adapter.setViewType(currentViewType);
|
||||
});
|
||||
|
||||
fabAdd.setOnClickListener(v -> requireActivity().getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
|
|
@ -60,30 +98,65 @@ public class FragmentManga extends Fragment {
|
|||
.addToBackStack(null)
|
||||
.commit());
|
||||
|
||||
loadMangaList();
|
||||
btnViewCompact.setOnClickListener(v -> setViewType(MangaAdapter.VIEW_COMPACT));
|
||||
btnViewNormal.setOnClickListener(v -> setViewType(MangaAdapter.VIEW_NORMAL));
|
||||
btnViewLarge.setOnClickListener(v -> setViewType(MangaAdapter.VIEW_LARGE));
|
||||
|
||||
return view;
|
||||
}
|
||||
setViewType(currentViewType);
|
||||
loadMoreMangas(currentPage);
|
||||
|
||||
private void loadMangaList() {
|
||||
api.getMangaByUser(userId).enqueue(new Callback<List<MangaEntity>>() {
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onResponse(Call<List<MangaEntity>> call, Response<List<MangaEntity>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
adapter = new MangaAdapter(response.body(), currentViewType,
|
||||
FragmentManga.this::showEditDialog,
|
||||
FragmentManga.this::deleteManga);
|
||||
recyclerView.setAdapter(adapter);
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al cargar la lista", Toast.LENGTH_SHORT).show();
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (layoutManager == null) return;
|
||||
|
||||
int visibleItemCount = layoutManager.getChildCount();
|
||||
int totalItemCount = layoutManager.getItemCount();
|
||||
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if (!isLoading && (firstVisibleItemPosition + visibleItemCount) >= totalItemCount - 4) {
|
||||
currentPage++;
|
||||
loadMoreMangas(currentPage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<MangaEntity>> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> {
|
||||
int bottomInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
|
||||
recyclerView.setPadding(
|
||||
recyclerView.getPaddingLeft(),
|
||||
recyclerView.getPaddingTop(),
|
||||
recyclerView.getPaddingRight(),
|
||||
bottomInset + 95
|
||||
);
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
||||
private void filterMangaList(String query) {
|
||||
List<MangaEntity> filtered = new ArrayList<>();
|
||||
for (MangaEntity manga : mangaList) {
|
||||
if (manga.getTitle().toLowerCase().contains(query.toLowerCase())) {
|
||||
filtered.add(manga);
|
||||
}
|
||||
}
|
||||
adapter.updateList(filtered);
|
||||
}
|
||||
|
||||
private void setViewType(int viewType) {
|
||||
currentViewType = viewType;
|
||||
|
||||
if (viewType == MangaAdapter.VIEW_LARGE) {
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2));
|
||||
} else {
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||
}
|
||||
|
||||
adapter = new MangaAdapter(mangaList, viewType,
|
||||
this::showEditDialog,
|
||||
this::deleteManga);
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void showEditDialog(MangaEntity manga) {
|
||||
|
|
@ -98,17 +171,48 @@ public class FragmentManga extends Fragment {
|
|||
api.deleteManga(manga.getId()).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (!isAdded()) return;
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Manga eliminado", Toast.LENGTH_SHORT).show();
|
||||
loadMangaList();
|
||||
Toast.makeText(requireContext(), "Manga eliminado", Toast.LENGTH_SHORT).show();
|
||||
currentPage = 1;
|
||||
mangaList.clear();
|
||||
loadMoreMangas(currentPage);
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(requireContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||
if (isAdded()) {
|
||||
Toast.makeText(requireContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMoreMangas(int page) {
|
||||
isLoading = true;
|
||||
api.getMangas(userId, page, PAGE_SIZE).enqueue(new Callback<MangaPageResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<MangaPageResponse> call, Response<MangaPageResponse> response) {
|
||||
if (!isAdded()) return;
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
List<MangaEntity> nuevos = response.body().getData();
|
||||
mangaList.addAll(nuevos);
|
||||
adapter.notifyItemRangeInserted(mangaList.size() - nuevos.size(), nuevos.size());
|
||||
isLoading = response.body().isHasNextPage();
|
||||
} else {
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<MangaPageResponse> call, Throwable t) {
|
||||
isLoading = false;
|
||||
if (isAdded()) {
|
||||
Toast.makeText(requireContext(), "Error al cargar más mangas", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,25 +3,29 @@ package com.santiparra.yomitrack.ui.fragments.profile;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||
|
||||
import com.santiparra.yomitrack.utils.ActivityLog;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
|
|
@ -30,111 +34,140 @@ import retrofit2.Response;
|
|||
|
||||
public class FragmentProfile extends Fragment {
|
||||
|
||||
private TextView textUsername;
|
||||
private LinearLayout animeStatsContainer, mangaStatsContainer;
|
||||
private ImageView avatarImage, coverImage;
|
||||
private TextView usernameText;
|
||||
private EditText editStatus, editBiography;
|
||||
private Button buttonPostStatus, buttonSaveBio;
|
||||
private LinearLayout animeStatsContainer, mangaStatsContainer, activityContainer;
|
||||
private ApiService api;
|
||||
private int userId;
|
||||
private String username;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_profile, container, false);
|
||||
|
||||
textUsername = view.findViewById(R.id.usernameText);
|
||||
avatarImage = view.findViewById(R.id.avatarImage);
|
||||
coverImage = view.findViewById(R.id.coverImage);
|
||||
usernameText = view.findViewById(R.id.usernameText);
|
||||
editStatus = view.findViewById(R.id.editStatus);
|
||||
editBiography = view.findViewById(R.id.editBiography);
|
||||
buttonPostStatus = view.findViewById(R.id.buttonPostStatus);
|
||||
buttonSaveBio = view.findViewById(R.id.buttonSaveBio);
|
||||
animeStatsContainer = view.findViewById(R.id.animeStatsContainer);
|
||||
mangaStatsContainer = view.findViewById(R.id.mangaStatsContainer);
|
||||
activityContainer = view.findViewById(R.id.activityContainer);
|
||||
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("userId", -1);
|
||||
username = prefs.getString("username", "Usuario");
|
||||
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("current_user_id", -1);
|
||||
|
||||
if (userId == -1) {
|
||||
textUsername.setText("Invitado");
|
||||
Toast.makeText(getContext(), "Estadísticas no disponibles en modo invitado", Toast.LENGTH_SHORT).show();
|
||||
return view;
|
||||
}
|
||||
|
||||
textUsername.setText("Usuario #" + userId);
|
||||
usernameText.setText(username);
|
||||
|
||||
loadStats();
|
||||
loadActivity();
|
||||
|
||||
buttonPostStatus.setOnClickListener(v -> postStatus());
|
||||
buttonSaveBio.setOnClickListener(v -> saveBiography());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void loadStats() {
|
||||
animeStatsContainer.removeAllViews();
|
||||
mangaStatsContainer.removeAllViews();
|
||||
|
||||
api.getAnimeByUser(userId).enqueue(new Callback<List<AnimeEntity>>() {
|
||||
api.getUserStats(userId).enqueue(new Callback<Map<String, Map<String, Integer>>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<AnimeEntity>> call, Response<List<AnimeEntity>> response) {
|
||||
public void onResponse(Call<Map<String, Map<String, Integer>>> call, Response<Map<String, Map<String, Integer>>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
showStats(animeStatsContainer, "Anime", countByStatus(response.body()));
|
||||
Map<String, Integer> animeStats = response.body().get("animeStats");
|
||||
Map<String, Integer> mangaStats = response.body().get("mangaStats");
|
||||
|
||||
populateStats(animeStatsContainer, animeStats);
|
||||
populateStats(mangaStatsContainer, mangaStats);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<AnimeEntity>> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error al cargar anime", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
api.getMangaByUser(userId).enqueue(new Callback<List<MangaEntity>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<MangaEntity>> call, Response<List<MangaEntity>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
showStats(mangaStatsContainer, "Manga", countByStatus(response.body()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<MangaEntity>> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error al cargar manga", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
public void onFailure(Call<Map<String, Map<String, Integer>>> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
|
||||
private Map<String, Integer> countByStatus(List<?> items) {
|
||||
Map<String, Integer> counts = new HashMap<>();
|
||||
for (Object item : items) {
|
||||
String status = "";
|
||||
if (item instanceof AnimeEntity) {
|
||||
status = ((AnimeEntity) item).getStatus();
|
||||
} else if (item instanceof MangaEntity) {
|
||||
status = ((MangaEntity) item).getStatus();
|
||||
}
|
||||
counts.put(status, counts.getOrDefault(status, 0) + 1);
|
||||
}
|
||||
return counts;
|
||||
}
|
||||
|
||||
private void showStats(LinearLayout container, String category, Map<String, Integer> data) {
|
||||
TextView title = new TextView(getContext());
|
||||
title.setText(category.toUpperCase());
|
||||
title.setTextSize(18);
|
||||
title.setPadding(0, 24, 0, 12);
|
||||
container.addView(title);
|
||||
|
||||
private void populateStats(LinearLayout container, Map<String, Integer> stats) {
|
||||
container.removeAllViews();
|
||||
int total = 0;
|
||||
for (int count : data.values()) total += count;
|
||||
for (int count : stats.values()) total += count;
|
||||
|
||||
for (Map.Entry<String, Integer> entry : data.entrySet()) {
|
||||
String status = entry.getKey();
|
||||
int count = entry.getValue();
|
||||
int percent = (int) ((count / (float) total) * 100);
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
for (Map.Entry<String, Integer> entry : stats.entrySet()) {
|
||||
View statView = inflater.inflate(R.layout.item_stat_bar, container, false);
|
||||
TextView label = statView.findViewById(R.id.statLabelFull);
|
||||
ProgressBar bar = statView.findViewById(R.id.statProgressBar);
|
||||
|
||||
TextView label = new TextView(getContext());
|
||||
label.setText(status + ": " + count + " (" + percent + "%)");
|
||||
label.setTextSize(16);
|
||||
container.addView(label);
|
||||
|
||||
ProgressBar progress = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleHorizontal);
|
||||
progress.setMax(100);
|
||||
progress.setProgress(percent);
|
||||
progress.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
));
|
||||
container.addView(progress);
|
||||
label.setText(String.format(Locale.getDefault(), "%s • %d", entry.getKey(), entry.getValue()));
|
||||
int progress = total > 0 ? (entry.getValue() * 100 / total) : 0;
|
||||
bar.setProgress(progress);
|
||||
container.addView(statView);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadActivity() {
|
||||
api.getActivityLog(userId).enqueue(new Callback<List<ActivityLog>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<ActivityLog>> call, Response<List<ActivityLog>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
activityContainer.removeAllViews();
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
for (ActivityLog log : response.body()) {
|
||||
View card = inflater.inflate(R.layout.item_activity_card, activityContainer, false);
|
||||
((TextView) card.findViewById(R.id.activityUser)).setText(username);
|
||||
((TextView) card.findViewById(R.id.activityAction)).setText(log.getAction());
|
||||
((TextView) card.findViewById(R.id.activityTitle)).setText(log.getMediaTitle());
|
||||
((TextView) card.findViewById(R.id.activityTime)).setText(log.getTimestamp());
|
||||
activityContainer.addView(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<ActivityLog>> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void postStatus() {
|
||||
String status = editStatus.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(status)) {
|
||||
Toast.makeText(getContext(), "Escribe algo primero", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> post = new HashMap<>();
|
||||
post.put("userId", userId);
|
||||
post.put("action", "publicó");
|
||||
post.put("mediaTitle", status);
|
||||
|
||||
api.postActivity(post).enqueue(new Callback<JSONObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JSONObject> call, Response<JSONObject> response) {
|
||||
if (response.isSuccessful()) {
|
||||
editStatus.setText("");
|
||||
loadActivity();
|
||||
Toast.makeText(getContext(), "Publicado", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JSONObject> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error al publicar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveBiography() {
|
||||
String bio = editBiography.getText().toString().trim();
|
||||
// Aquí podrías guardar biografía en base de datos si se desea.
|
||||
Toast.makeText(getContext(), "Biografía guardada", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +1,84 @@
|
|||
// RegisterFragment.java solucionado para evitar NPE en onFailure()
|
||||
|
||||
package com.santiparra.yomitrack.ui.fragments.register;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.databinding.FragmentRegisterBinding;
|
||||
import com.santiparra.yomitrack.db.entities.UserEntity;
|
||||
import com.santiparra.yomitrack.model.RegisterResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class RegisterFragment extends Fragment {
|
||||
|
||||
private EditText usernameEditText;
|
||||
private EditText passwordEditText;
|
||||
private Button registerButton;
|
||||
private ApiService api;
|
||||
private FragmentRegisterBinding binding;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_register, container, false);
|
||||
|
||||
usernameEditText = view.findViewById(R.id.editTextUsernameRegister);
|
||||
passwordEditText = view.findViewById(R.id.editTextPasswordRegister);
|
||||
registerButton = view.findViewById(R.id.buttonRegister);
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
registerButton.setOnClickListener(v -> attemptRegister());
|
||||
|
||||
return view;
|
||||
public RegisterFragment() {
|
||||
}
|
||||
|
||||
private void attemptRegister() {
|
||||
String username = usernameEditText.getText().toString().trim();
|
||||
String password = passwordEditText.getText().toString().trim();
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
binding = FragmentRegisterBinding.inflate(inflater, container, false);
|
||||
|
||||
binding.buttonRegister.setOnClickListener(v -> registerUser());
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
private void registerUser() {
|
||||
String username = binding.editTextUsernameRegister.getText().toString().trim();
|
||||
String password = binding.editTextPasswordRegister.getText().toString().trim();
|
||||
|
||||
if (username.isEmpty() || password.isEmpty()) {
|
||||
safeToast("Todos los campos son obligatorios");
|
||||
showToast("Todos los campos son obligatorios");
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, String> request = new HashMap<>();
|
||||
request.put("username", username);
|
||||
request.put("password", password);
|
||||
UserEntity user = new UserEntity(username, password);
|
||||
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
api.registerUser(request).enqueue(new Callback<RegisterResponse>() {
|
||||
apiService.registerUser(user).enqueue(new Callback<RegisterResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<RegisterResponse> call, Response<RegisterResponse> response) {
|
||||
if (isAdded() && response.isSuccessful() && response.body() != null && response.body().getUserId() > 0) {
|
||||
int userId = response.body().getUserId();
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
prefs.edit().putInt("current_user_id", userId).apply();
|
||||
safeToast("Registro exitoso");
|
||||
requireActivity().finish();
|
||||
public void onResponse(@NonNull Call<RegisterResponse> call, @NonNull Response<RegisterResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isSuccess()) {
|
||||
showToast("Registro exitoso");
|
||||
NavController navController = Navigation.findNavController(binding.getRoot());
|
||||
navController.popBackStack(); // Volver al LoginFragment
|
||||
} else {
|
||||
safeToast("Error al registrar usuario");
|
||||
String errorMsg = (response.body() != null && response.body().getMessage() != null)
|
||||
? response.body().getMessage()
|
||||
: "Error desconocido al registrar";
|
||||
showToast(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<RegisterResponse> call, Throwable t) {
|
||||
safeToast("Fallo de conexión: " + t.getMessage());
|
||||
public void onFailure(@NonNull Call<RegisterResponse> call, @NonNull Throwable t) {
|
||||
showToast("Fallo de red: " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void safeToast(String message) {
|
||||
if (isAdded() && getContext() != null) {
|
||||
Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
private void showToast(String msg) {
|
||||
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
package com.santiparra.yomitrack.utils;
|
||||
|
||||
import com.santiparra.yomitrack.model.UserStats;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StatsHelper {
|
||||
|
||||
public static List<UserStats> getAnimeStats() {
|
||||
List<UserStats> stats = new ArrayList<>();
|
||||
stats.add(new UserStats("Watching", 42, 8));
|
||||
stats.add(new UserStats("Completed", 265, 51));
|
||||
stats.add(new UserStats("On Hold", 10, 2));
|
||||
stats.add(new UserStats("Dropped", 5, 1));
|
||||
stats.add(new UserStats("Plan to Watch", 198, 38));
|
||||
return stats;
|
||||
}
|
||||
|
||||
public static List<UserStats> getMangaStats() {
|
||||
List<UserStats> stats = new ArrayList<>();
|
||||
stats.add(new UserStats("Reading", 31, 10));
|
||||
stats.add(new UserStats("Completed", 121, 55));
|
||||
stats.add(new UserStats("On Hold", 5, 3));
|
||||
stats.add(new UserStats("Dropped", 4, 2));
|
||||
stats.add(new UserStats("Plan to Read", 28, 30));
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 911 KiB |
|
|
@ -1,3 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
|
|
@ -16,21 +15,19 @@
|
|||
<!-- Banner -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/bannerLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:background="@drawable/sample_cover"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageViewBanner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="Banner"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/sample_cover"
|
||||
android:contentDescription="Banner" />
|
||||
android:src="@drawable/sample_cover" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageViewAvatar"
|
||||
|
|
@ -39,39 +36,38 @@
|
|||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:src="@drawable/ic_profile"
|
||||
android:background="@drawable/circle_mask"
|
||||
android:scaleType="centerCrop"
|
||||
android:clipToOutline="true"
|
||||
android:contentDescription="Avatar" />
|
||||
android:contentDescription="Avatar"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_profile" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewUsername"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/imageViewAvatar"
|
||||
android:layout_alignBottom="@id/imageViewAvatar"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_toEndOf="@id/imageViewAvatar"
|
||||
android:text="Usuario"
|
||||
android:textColor="@android:color/white"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp" />
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Búsqueda + botones -->
|
||||
<LinearLayout
|
||||
android:id="@+id/searchLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/bannerLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
app:layout_constraintTop_toBottomOf="@id/bannerLayout">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSearch"
|
||||
|
|
@ -80,36 +76,36 @@
|
|||
android:layout_weight="1"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:hint="Buscar anime..."
|
||||
android:inputType="text"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
android:inputType="text" />
|
||||
android:textSize="14sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewCompact"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:src="@drawable/ic_view_compact"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Vista Compacta" />
|
||||
android:contentDescription="Vista Compacta"
|
||||
android:src="@drawable/ic_view_compact" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewNormal"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_view_normal"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Vista Normal" />
|
||||
android:contentDescription="Vista Normal"
|
||||
android:src="@drawable/ic_view_normal" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewLarge"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_view_large"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Vista Grande" />
|
||||
android:contentDescription="Vista Grande"
|
||||
android:src="@drawable/ic_view_large" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Lista de animes -->
|
||||
|
|
@ -117,14 +113,14 @@
|
|||
android:id="@+id/recyclerViewAnime"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:clipToPadding="false"
|
||||
android:padding="8dp"
|
||||
android:paddingBottom="96dp"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchLayout"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchLayout" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- FAB correctamente posicionado -->
|
||||
|
|
@ -134,10 +130,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:layout_marginBottom="65dp"
|
||||
android:contentDescription="Agregar anime"
|
||||
android:src="@drawable/ic_add"
|
||||
android:tint="@android:color/white"
|
||||
app:backgroundTint="@color/primary" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -2,40 +2,40 @@
|
|||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:paddingTop="100dp"
|
||||
android:paddingBottom="80dp"
|
||||
android:fillViewport="true">
|
||||
android:paddingBottom="80dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextAnimeTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:hint="Título del anime"
|
||||
android:inputType="text"
|
||||
android:padding="12dp"
|
||||
android:background="@drawable/edit_text_background" />
|
||||
android:padding="12dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextScore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:hint="Puntuación (0-100)"
|
||||
android:inputType="number"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:inputType="number" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:hint="Progreso (episodios vistos)"
|
||||
android:inputType="number"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:inputType="number" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerStatus"
|
||||
|
|
@ -55,9 +55,18 @@
|
|||
android:id="@+id/buttonSaveAnime"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Guardar cambios"
|
||||
android:layout_marginTop="24dp"
|
||||
android:backgroundTint="@color/primary"
|
||||
android:text="Guardar cambios"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonDeleteAnime"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:backgroundTint="@android:color/holo_red_dark"
|
||||
android:text="Eliminar anime"
|
||||
android:textColor="@android:color/white" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
|
|
|||
|
|
@ -1,40 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:paddingTop="100dp"
|
||||
android:paddingBottom="80dp"
|
||||
android:fillViewport="true">
|
||||
android:paddingBottom="80dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextMangaTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:hint="Título del manga"
|
||||
android:inputType="text"
|
||||
android:padding="12dp"
|
||||
android:background="@drawable/edit_text_background" />
|
||||
android:padding="12dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextScore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:hint="Puntuación (0-100)"
|
||||
android:inputType="number"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:inputType="number" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:hint="Progreso (capítulos leídos)"
|
||||
android:inputType="number"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:inputType="number" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerStatus"
|
||||
|
|
@ -54,9 +55,18 @@
|
|||
android:id="@+id/buttonSaveManga"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Guardar cambios"
|
||||
android:layout_marginTop="24dp"
|
||||
android:backgroundTint="@color/primary"
|
||||
android:text="Guardar cambios"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonDeleteManga"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:backgroundTint="@android:color/holo_red_dark"
|
||||
android:text="Eliminar manga"
|
||||
android:textColor="@android:color/white" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
|
|
|||
|
|
@ -1,111 +1,140 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.fragments.manga_list.FragmentManga">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- Banner superior reducido -->
|
||||
<!-- Banner -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/bannerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:layout_height="160dp"
|
||||
android:background="@drawable/sample_cover"
|
||||
android:padding="12dp">
|
||||
android:padding="12dp"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageViewBanner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="Banner"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/sample_cover"
|
||||
android:contentDescription="Banner" />
|
||||
android:src="@drawable/sample_cover" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="bottom|start"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:layout_alignParentBottom="true">
|
||||
<ImageView
|
||||
android:id="@+id/imageViewAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="@drawable/circle_mask"
|
||||
android:clipToOutline="true"
|
||||
android:contentDescription="Avatar"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_profile" />
|
||||
|
||||
<!-- Avatar -->
|
||||
<ImageView
|
||||
android:id="@+id/imageViewAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_profile"
|
||||
android:background="@drawable/circle_mask"
|
||||
android:scaleType="centerCrop"
|
||||
android:clipToOutline="true"
|
||||
android:contentDescription="Avatar"
|
||||
android:layout_marginEnd="12dp" />
|
||||
|
||||
<!-- Nombre -->
|
||||
<TextView
|
||||
android:id="@+id/textViewUsername"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Usuario"
|
||||
android:textColor="@android:color/white"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:gravity="center_vertical" />
|
||||
|
||||
<!-- Botón de cambiar vista -->
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewCompact"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_view_compact" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_view_normal" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_view_large" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/textViewUsername"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@id/imageViewAvatar"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_toEndOf="@id/imageViewAvatar"
|
||||
android:text="Usuario"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Lista scrollable -->
|
||||
<!-- Búsqueda + botones -->
|
||||
<LinearLayout
|
||||
android:id="@+id/searchLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/bannerLayout">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSearch"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/edit_text_background"
|
||||
android:hint="Buscar manga..."
|
||||
android:inputType="text"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewCompact"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Vista Compacta"
|
||||
android:src="@drawable/ic_view_compact" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewNormal"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Vista Normal"
|
||||
android:src="@drawable/ic_view_normal" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnViewLarge"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Vista Grande"
|
||||
android:src="@drawable/ic_view_large" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Lista de mangas -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerViewManga"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="100dp"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical" />
|
||||
</LinearLayout>
|
||||
android:padding="8dp"
|
||||
android:paddingBottom="96dp"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchLayout" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- FAB flotante -->
|
||||
<!-- FAB para añadir manga -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fabAddManga"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="65dp"
|
||||
android:contentDescription="Agregar manga"
|
||||
android:src="@drawable/ic_add"
|
||||
android:tint="@android:color/white"
|
||||
app:backgroundTint="@color/primary" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -6,12 +5,12 @@
|
|||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="32dp">
|
||||
|
||||
<!-- Header con avatar + nombre -->
|
||||
<!-- Encabezado: Cover, Avatar y Nombre -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp">
|
||||
|
|
@ -27,9 +26,9 @@
|
|||
android:id="@+id/avatarImage"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@drawable/circle_mask"
|
||||
android:clipToOutline="true"
|
||||
android:scaleType="centerCrop"
|
||||
|
|
@ -40,114 +39,93 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@id/avatarImage"
|
||||
android:layout_toEndOf="@id/avatarImage"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_toEndOf="@id/avatarImage"
|
||||
android:text="BtwIsSanti"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Descripción en tarjeta -->
|
||||
<androidx.cardview.widget.CardView
|
||||
|
||||
<!-- Biografía -->
|
||||
<EditText
|
||||
android:id="@+id/editBiography"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="6dp">
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/edittext_background"
|
||||
android:hint="Escribe tu biografía aquí"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="3" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@color/primary">
|
||||
<Button
|
||||
android:id="@+id/buttonSaveBio"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Guardar Biografía" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/descriptionTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Description"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profileDescriptionText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Eiko is my waifu right now. Mai and Mikasa is my second wife."
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textSize="16sp"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginTop="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewSeeMore"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Ver más"
|
||||
android:textColor="@color/activeTint"
|
||||
android:textSize="14sp"
|
||||
android:paddingTop="4dp" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Estadísticas de anime -->
|
||||
<!-- Estadísticas de Anime -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Anime Stats"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/animeStatsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="16dp" />
|
||||
android:layout_marginBottom="16dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<!-- Estadísticas de manga -->
|
||||
<!-- Estadísticas de Manga -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Manga Stats"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/mangaStatsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="16dp" />
|
||||
android:layout_marginBottom="16dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<!-- Estado / Pensamiento -->
|
||||
<EditText
|
||||
android:id="@+id/editStatus"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/edittext_background"
|
||||
android:hint="¿Qué estás pensando?"
|
||||
android:inputType="text" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonPostStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Publicar Estado" />
|
||||
|
||||
<!-- Actividad reciente -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recent Activity"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Actividad Reciente"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/activityContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:paddingBottom="8dp" />
|
||||
android:orientation="vertical" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_card"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp">
|
||||
|
||||
|
|
@ -8,31 +10,31 @@
|
|||
android:id="@+id/imageCover"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="96dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="Portada" />
|
||||
android:contentDescription="Portada"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Título"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Estado"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textScore"
|
||||
|
|
@ -48,6 +50,7 @@
|
|||
android:text="Progreso: 10 eps"
|
||||
android:textSize="14sp" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textType"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_card"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
|
||||
|
|
@ -9,14 +11,16 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Título Compacto"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Estado"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
android:id="@+id/imageCover"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="240dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="@drawable/rectangle_placeholder"
|
||||
android:contentDescription="Portada" />
|
||||
android:contentDescription="Portada"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<!-- Progreso en esquina inferior izquierda -->
|
||||
<TextView
|
||||
|
|
@ -19,11 +19,11 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:layout_margin="6dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="6/12"
|
||||
android:textColor="#FF4444"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp"
|
||||
android:background="@android:color/transparent" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- Título con fondo oscuro -->
|
||||
<TextView
|
||||
|
|
@ -32,12 +32,12 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="#99000000"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:padding="6dp"
|
||||
android:text="Nombre del Anime"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:padding="6dp"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end" />
|
||||
android:textSize="14sp" />
|
||||
|
||||
<!-- Indicador de estado (ej: Watching) -->
|
||||
<View
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_card"
|
||||
android:orientation="horizontal"
|
||||
android:padding="12dp">
|
||||
|
||||
|
|
@ -8,31 +10,31 @@
|
|||
android:id="@+id/imageCover"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="96dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="Portada" />
|
||||
android:contentDescription="Portada"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Título"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Estado"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textScore"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_card"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
|
||||
|
|
@ -9,14 +11,14 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Título Compacto"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Estado"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
android:id="@+id/imageCover"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="240dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:background="@drawable/rectangle_placeholder"
|
||||
android:contentDescription="Portada" />
|
||||
android:contentDescription="Portada"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<!-- Progreso en esquina inferior izquierda -->
|
||||
<TextView
|
||||
|
|
@ -19,11 +19,11 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:layout_margin="6dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="6/12"
|
||||
android:textColor="#FF4444"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp"
|
||||
android:background="@android:color/transparent" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- Título con fondo oscuro -->
|
||||
<TextView
|
||||
|
|
@ -32,12 +32,12 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="#99000000"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:padding="6dp"
|
||||
android:text="Nombre del Manga"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:padding="6dp"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end" />
|
||||
android:textSize="14sp" />
|
||||
|
||||
<!-- Indicador de estado (ej: Watching) -->
|
||||
<View
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
<fragment
|
||||
android:id="@+id/loginFragment"
|
||||
android:name="com.santiparra.yomitrack.ui.fragments.login.LoginFragment"
|
||||
android:label="Login" >
|
||||
android:label="Login">
|
||||
<action
|
||||
android:id="@+id/action_login_to_register"
|
||||
android:id="@+id/action_loginFragment_to_registerFragment"
|
||||
app:destination="@id/registerFragment" />
|
||||
</fragment>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,4 +51,5 @@
|
|||
<item name="buttonSaveAnime" type="id" />
|
||||
<item name="statusDot" type="id" />
|
||||
<item name="editSearch" type="id" />
|
||||
<item name="animeStatText" type="id" />
|
||||
</resources>
|
||||
Loading…
Reference in New Issue