Terminacion de la clase FragmentProfile que ya tiene toda la funcionalidad que a de tener y optimizacion de otras para que funcione y creacion de javas y xml!
This commit is contained in:
parent
c7053368a2
commit
b7770c9fc6
Binary file not shown.
|
|
@ -53,6 +53,9 @@ public interface ApiService {
|
|||
@Query("size") int size
|
||||
);
|
||||
|
||||
@GET("anime/airing")
|
||||
Call<List<AnimeEntity>> getAiringAnime();
|
||||
|
||||
@PUT("anime/{id}")
|
||||
Call<ApiResponse> updateAnime(@Path("id") int animeId, @Body AnimeEntity anime);
|
||||
|
||||
|
|
@ -73,6 +76,12 @@ public interface ApiService {
|
|||
@Query("size") int size
|
||||
);
|
||||
|
||||
@GET("manga/user/{userId}/status/{status}")
|
||||
Call<List<MangaEntity>> getMangaByUserAndStatus(
|
||||
@Path("userId") int userId,
|
||||
@Path("status") String status
|
||||
);
|
||||
|
||||
@PUT("manga/{id}")
|
||||
Call<ApiResponse> updateManga(@Path("id") int mangaId, @Body MangaEntity manga);
|
||||
|
||||
|
|
@ -96,6 +105,12 @@ public interface ApiService {
|
|||
@Path("activityId") int activityId
|
||||
);
|
||||
|
||||
@GET("anime/user/{userId}/status/{status}")
|
||||
Call<List<AnimeEntity>> getAnimeByUserAndStatus(
|
||||
@Path("userId") int userId,
|
||||
@Path("status") String status
|
||||
);
|
||||
|
||||
@POST("api/activity/like")
|
||||
Call<JsonObject> postLike(@Body JsonObject body);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,19 @@ public class AnimeEntity implements Serializable {
|
|||
private String imageUrl;
|
||||
private int totalEpisodes;
|
||||
|
||||
public AnimeEntity() {
|
||||
}
|
||||
|
||||
public AnimeEntity(int id, String title, String status, int userId, String imageUrl, int progress, int score, int totalEpisodes) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.status = status;
|
||||
this.userId = userId;
|
||||
this.imageUrl = imageUrl;
|
||||
this.progress = progress;
|
||||
this.score = score;
|
||||
this.totalEpisodes = totalEpisodes;
|
||||
}
|
||||
|
||||
// Getters y Setters
|
||||
public int getId() {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,20 @@ public class MangaEntity implements Serializable {
|
|||
private String imageUrl;
|
||||
private int totalChapters;
|
||||
|
||||
public MangaEntity() {
|
||||
}
|
||||
|
||||
public MangaEntity(int id, String title, String status, int userId, String imageUrl, int progress, int score, int totalChapters) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.status = status;
|
||||
this.userId = userId;
|
||||
this.imageUrl = imageUrl;
|
||||
this.progress = progress;
|
||||
this.score = score;
|
||||
this.totalChapters = totalChapters;
|
||||
}
|
||||
|
||||
// Getters y Setters
|
||||
|
||||
public int getId() {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,20 @@ package com.santiparra.yomitrack.model;
|
|||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
|
@ -19,40 +23,74 @@ import retrofit2.Response;
|
|||
|
||||
public class CommentDialog extends Dialog {
|
||||
|
||||
private final int userId;
|
||||
private final int activityId;
|
||||
private final String replyToUsername;
|
||||
private final Runnable onCommentPosted;
|
||||
|
||||
private EditText editComment;
|
||||
private Button buttonSend;
|
||||
private ApiService api;
|
||||
|
||||
public CommentDialog(@NonNull Context context, int userId, int activityId, Runnable onCommentPosted) {
|
||||
this(context, userId, activityId, onCommentPosted, null);
|
||||
}
|
||||
|
||||
public CommentDialog(@NonNull Context context, int userId, int activityId, Runnable onCommentPosted, String replyToUsername) {
|
||||
super(context);
|
||||
this.userId = userId;
|
||||
this.activityId = activityId;
|
||||
this.replyToUsername = replyToUsername;
|
||||
this.onCommentPosted = onCommentPosted;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.dialog_comment);
|
||||
|
||||
EditText commentInput = findViewById(R.id.commentInput);
|
||||
Button sendButton = findViewById(R.id.sendComment);
|
||||
editComment = findViewById(R.id.commentInput);
|
||||
buttonSend = findViewById(R.id.sendComment);
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
sendButton.setOnClickListener(v -> {
|
||||
String commentText = commentInput.getText().toString().trim();
|
||||
if (commentText.isEmpty()) {
|
||||
Toast.makeText(context, "Escribe un comentario", Toast.LENGTH_SHORT).show();
|
||||
// Prefill @usuario si es respuesta
|
||||
if (replyToUsername != null && !replyToUsername.isEmpty()) {
|
||||
editComment.setText("@" + replyToUsername + " ");
|
||||
editComment.setSelection(editComment.getText().length()); // Coloca el cursor al final
|
||||
}
|
||||
|
||||
buttonSend.setOnClickListener(v -> postComment());
|
||||
}
|
||||
|
||||
private void postComment() {
|
||||
String text = editComment.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
Toast.makeText(getContext(), "Escribe un comentario", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("userId", userId);
|
||||
body.addProperty("activityId", activityId);
|
||||
body.addProperty("text", commentText);
|
||||
JsonObject comment = new JsonObject();
|
||||
comment.addProperty("userId", userId);
|
||||
comment.addProperty("activityId", activityId);
|
||||
comment.addProperty("text", text);
|
||||
|
||||
ApiClient.getClient().create(ApiService.class).postComment(body).enqueue(new Callback<JsonObject>() {
|
||||
api.postComment(comment).enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(context, "Comentario enviado", Toast.LENGTH_SHORT).show();
|
||||
dismiss();
|
||||
onCommentPosted.run(); // recarga comentarios en FragmentProfile
|
||||
Toast.makeText(getContext(), "Comentario enviado", Toast.LENGTH_SHORT).show();
|
||||
if (onCommentPosted != null) onCommentPosted.run();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error al comentar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
Toast.makeText(context, "Error al comentar", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,44 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
public class CommentModel {
|
||||
public String text;
|
||||
public boolean liked;
|
||||
private int id;
|
||||
private String text;
|
||||
private boolean liked;
|
||||
private String username;
|
||||
private String avatarUrl;
|
||||
private String created_at;
|
||||
|
||||
|
||||
public CommentModel(String text) {
|
||||
this.text = text;
|
||||
this.liked = false;
|
||||
}
|
||||
|
||||
// Constructor completo (opcional)
|
||||
public CommentModel(int id, String text, boolean liked, String username, String avatarUrl, String created_at) {
|
||||
this.id = id;
|
||||
this.text = text;
|
||||
this.liked = liked;
|
||||
this.username = username;
|
||||
this.avatarUrl = avatarUrl;
|
||||
this.created_at = created_at;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public boolean isLiked() {
|
||||
return liked;
|
||||
}
|
||||
|
||||
public void setLiked(boolean liked) {
|
||||
this.liked = liked;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,26 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
/**
|
||||
* Modelo general de ítem para mostrar en secciones del home.
|
||||
* Se usa tanto para anime como manga.
|
||||
*/
|
||||
public class ItemModel {
|
||||
private String title;
|
||||
private String progress;
|
||||
private String imageUrl;
|
||||
private ContentType contentType;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ItemModel implements Serializable {
|
||||
|
||||
public enum ContentType {
|
||||
ANIME,
|
||||
MANGA
|
||||
}
|
||||
|
||||
public ItemModel(String title, String progress, String imageUrl, ContentType contentType) {
|
||||
private final String title;
|
||||
private final String progress;
|
||||
private final String imageUrl;
|
||||
private final ContentType type;
|
||||
private final Object object;
|
||||
|
||||
public ItemModel(String title, String progress, String imageUrl, ContentType type, Object object) {
|
||||
this.title = title;
|
||||
this.progress = progress;
|
||||
this.imageUrl = imageUrl;
|
||||
this.contentType = contentType;
|
||||
this.type = type;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
|
|
@ -34,23 +35,11 @@ public class ItemModel {
|
|||
return imageUrl;
|
||||
}
|
||||
|
||||
public ContentType getContentType() {
|
||||
return contentType;
|
||||
public ContentType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setProgress(String progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public void setContentType(ContentType contentType) {
|
||||
this.contentType = contentType;
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,40 @@
|
|||
package com.santiparra.yomitrack.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Modelo de actividad reciente para mostrar acciones de usuario.
|
||||
*/
|
||||
public class RecentActivityModel {
|
||||
public int activityId; // ← agregar esto
|
||||
public String user;
|
||||
public String action;
|
||||
public String title;
|
||||
public String time;
|
||||
public String imageUrl;
|
||||
public List<CommentModel> comments = new ArrayList<>();
|
||||
|
||||
public RecentActivityModel(int activityId, String user, String action, String title, String time, String imageUrl) {
|
||||
this.activityId = activityId;
|
||||
private final int id;
|
||||
private final int userId;
|
||||
private final String user;
|
||||
public final String action;
|
||||
public final String title;
|
||||
public final String imageUrl;
|
||||
public final String time;
|
||||
public final List<CommentModel> comments;
|
||||
public boolean liked;
|
||||
|
||||
public RecentActivityModel(int id, int userId, String user, String action, String title, String imageUrl, String time, List<CommentModel> comments, boolean liked) {
|
||||
this.id = id;
|
||||
this.userId = userId;
|
||||
this.user = user;
|
||||
this.action = action;
|
||||
this.title = title;
|
||||
this.time = time;
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public void addComment(CommentModel comment) {
|
||||
comments.add(comment);
|
||||
this.time = time;
|
||||
this.comments = comments;
|
||||
this.liked = liked;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return activityId;
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,18 +9,23 @@ import android.widget.LinearLayout;
|
|||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.model.CommentDialog;
|
||||
import com.santiparra.yomitrack.model.CommentModel;
|
||||
import com.santiparra.yomitrack.model.RecentActivityModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RecentActivityAdapter extends RecyclerView.Adapter<RecentActivityAdapter.ActivityViewHolder> {
|
||||
private final List<RecentActivityModel> activityList;
|
||||
|
||||
public RecentActivityAdapter(List<RecentActivityModel> activityList) {
|
||||
private List<RecentActivityModel> activityList;
|
||||
private final int currentUserId;
|
||||
|
||||
public RecentActivityAdapter(List<RecentActivityModel> activityList, int currentUserId) {
|
||||
this.activityList = activityList;
|
||||
this.currentUserId = currentUserId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -33,7 +38,8 @@ public class RecentActivityAdapter extends RecyclerView.Adapter<RecentActivityAd
|
|||
@Override
|
||||
public void onBindViewHolder(@NonNull ActivityViewHolder holder, int position) {
|
||||
RecentActivityModel activity = activityList.get(position);
|
||||
holder.user.setText(activity.user);
|
||||
|
||||
holder.user.setText(activity.getUser());
|
||||
holder.action.setText(activity.action);
|
||||
holder.title.setText(activity.title);
|
||||
holder.time.setText(activity.time);
|
||||
|
|
@ -44,34 +50,86 @@ public class RecentActivityAdapter extends RecyclerView.Adapter<RecentActivityAd
|
|||
.into(holder.image);
|
||||
|
||||
holder.commentContainer.removeAllViews();
|
||||
|
||||
if (holder.commentContainer != null) {
|
||||
holder.commentContainer.removeAllViews();
|
||||
LayoutInflater inflater = LayoutInflater.from(holder.itemView.getContext());
|
||||
|
||||
for (CommentModel comment : activity.comments) {
|
||||
View commentView = LayoutInflater.from(holder.itemView.getContext())
|
||||
.inflate(R.layout.item_comment, holder.commentContainer, false);
|
||||
View commentView = inflater.inflate(R.layout.item_comment, holder.commentContainer, false);
|
||||
|
||||
TextView usernameView = commentView.findViewById(R.id.commentUsername);
|
||||
TextView commentText = commentView.findViewById(R.id.commentText);
|
||||
ImageButton commentLike = commentView.findViewById(R.id.commentLikeButton);
|
||||
TextView dateView = commentView.findViewById(R.id.commentDate);
|
||||
ImageView avatar = commentView.findViewById(R.id.commentAvatar);
|
||||
ImageButton likeButton = commentView.findViewById(R.id.commentLikeButton);
|
||||
ImageButton replyButton = commentView.findViewById(R.id.replyButton);
|
||||
|
||||
commentText.setText(comment.text);
|
||||
commentLike.setImageResource(comment.liked ? R.drawable.ic_heart_filled : R.drawable.ic_heart);
|
||||
commentLike.setColorFilter(comment.liked
|
||||
? holder.itemView.getContext().getColor(R.color.pink)
|
||||
: holder.itemView.getContext().getColor(R.color.textPrimary));
|
||||
usernameView.setText(comment.getUsername());
|
||||
commentText.setText(comment.getText());
|
||||
dateView.setText(comment.getCreatedAt());
|
||||
|
||||
commentLike.setOnClickListener(v -> {
|
||||
comment.liked = !comment.liked;
|
||||
commentLike.setImageResource(comment.liked ? R.drawable.ic_heart_filled : R.drawable.ic_heart);
|
||||
commentLike.setColorFilter(comment.liked
|
||||
? holder.itemView.getContext().getColor(R.color.pink)
|
||||
: holder.itemView.getContext().getColor(R.color.textPrimary));
|
||||
Glide.with(commentView.getContext())
|
||||
.load(comment.getAvatarUrl())
|
||||
.placeholder(R.drawable.rectangle_placeholder)
|
||||
.error(R.drawable.error_image)
|
||||
.into(avatar);
|
||||
|
||||
likeButton.setImageResource(comment.isLiked() ? R.drawable.ic_heart_filled : R.drawable.ic_heart_outline);
|
||||
likeButton.setColorFilter(commentView.getContext().getColor(comment.isLiked() ? R.color.pink : R.color.gray));
|
||||
|
||||
likeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean newLike = !comment.isLiked();
|
||||
comment.setLiked(newLike);
|
||||
likeButton.setImageResource(newLike ? R.drawable.ic_heart_filled : R.drawable.ic_heart_outline);
|
||||
likeButton.setColorFilter(commentView.getContext().getColor(newLike ? R.color.pink : R.color.gray));
|
||||
}
|
||||
});
|
||||
|
||||
replyButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int adapterPos = holder.getAdapterPosition();
|
||||
if (adapterPos == RecyclerView.NO_POSITION) return;
|
||||
RecentActivityModel activityItem = activityList.get(adapterPos);
|
||||
CommentDialog dialog = new CommentDialog(
|
||||
holder.itemView.getContext(),
|
||||
currentUserId,
|
||||
activityItem.getId(),
|
||||
() -> notifyItemChanged(adapterPos),
|
||||
comment.getUsername()
|
||||
);
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
|
||||
holder.commentContainer.addView(commentView);
|
||||
}
|
||||
|
||||
holder.commentButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int adapterPos = holder.getAdapterPosition();
|
||||
if (adapterPos == RecyclerView.NO_POSITION) return;
|
||||
RecentActivityModel activityItem = activityList.get(adapterPos);
|
||||
CommentDialog dialog = new CommentDialog(
|
||||
holder.itemView.getContext(),
|
||||
currentUserId,
|
||||
activityItem.getId(),
|
||||
() -> notifyItemChanged(adapterPos)
|
||||
);
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
|
||||
holder.likeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
activity.liked = !activity.liked;
|
||||
holder.likeButton.setImageResource(activity.liked ? R.drawable.ic_heart_filled : R.drawable.ic_heart_outline);
|
||||
holder.likeButton.setColorFilter(holder.itemView.getContext().getColor(
|
||||
activity.liked ? R.color.pink : R.color.textPrimary));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -79,12 +137,16 @@ public class RecentActivityAdapter extends RecyclerView.Adapter<RecentActivityAd
|
|||
return activityList.size();
|
||||
}
|
||||
|
||||
class ActivityViewHolder extends RecyclerView.ViewHolder {
|
||||
public void updateData(List<RecentActivityModel> newList) {
|
||||
this.activityList = newList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class ActivityViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView user, action, title, time;
|
||||
ImageView image;
|
||||
ImageButton likeButton, commentButton;
|
||||
LinearLayout commentContainer;
|
||||
boolean isLiked = false;
|
||||
|
||||
public ActivityViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
|
|
@ -95,24 +157,7 @@ public class RecentActivityAdapter extends RecyclerView.Adapter<RecentActivityAd
|
|||
image = itemView.findViewById(R.id.activityCover);
|
||||
likeButton = itemView.findViewById(R.id.likeButton);
|
||||
commentButton = itemView.findViewById(R.id.commentButton);
|
||||
commentContainer = itemView.findViewById(R.id.commentsContainer); // <- protección aplicada
|
||||
|
||||
likeButton.setOnClickListener(v -> {
|
||||
isLiked = !isLiked;
|
||||
likeButton.setImageResource(isLiked ? R.drawable.ic_heart_filled : R.drawable.ic_heart);
|
||||
likeButton.setColorFilter(isLiked
|
||||
? itemView.getContext().getColor(R.color.pink)
|
||||
: itemView.getContext().getColor(R.color.textPrimary));
|
||||
});
|
||||
|
||||
commentButton.setOnClickListener(v -> {
|
||||
RecentActivityModel activity = activityList.get(getAdapterPosition());
|
||||
int activityId = activity.getId();
|
||||
int userId = this.user.getId();
|
||||
|
||||
CommentDialog dialog = new CommentDialog(itemView.getContext(), userId, activityId, () -> {});
|
||||
dialog.show();
|
||||
});
|
||||
commentContainer = itemView.findViewById(R.id.commentsContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package com.santiparra.yomitrack.ui.fragments.browse;
|
|||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
|
|
@ -22,17 +24,27 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.santiparra.yomitrack.R;
|
||||
import com.santiparra.yomitrack.api.ApiClient;
|
||||
import com.santiparra.yomitrack.api.ApiService;
|
||||
import com.santiparra.yomitrack.model.AniListMedia;
|
||||
import com.santiparra.yomitrack.model.ItemModel;
|
||||
import com.santiparra.yomitrack.model.adapters.browser_section_adapter.BrowseGridAdapter;
|
||||
import com.santiparra.yomitrack.model.adapters.anilist_adapter.AniListSearchAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class FragmentBrowse extends Fragment {
|
||||
|
||||
private Spinner spinnerType;
|
||||
private EditText editTextSearch;
|
||||
private LinearLayout sectionContainer;
|
||||
private RecyclerView recyclerViewResults;
|
||||
private AniListSearchAdapter searchAdapter;
|
||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||
private Runnable searchRunnable;
|
||||
|
||||
private final List<ItemModel> animeList = new ArrayList<>();
|
||||
private final List<ItemModel> mangaList = new ArrayList<>();
|
||||
|
|
@ -46,145 +58,56 @@ public class FragmentBrowse extends Fragment {
|
|||
spinnerType = view.findViewById(R.id.spinnerType);
|
||||
editTextSearch = view.findViewById(R.id.editTextSearch);
|
||||
sectionContainer = view.findViewById(R.id.sectionContainer);
|
||||
recyclerViewResults = view.findViewById(R.id.recyclerViewResults);
|
||||
recyclerViewResults.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
||||
View statusBarSpacer = view.findViewById(R.id.statusBarSpacer);
|
||||
int statusBarHeight = getStatusBarHeight();
|
||||
ViewGroup.LayoutParams params = statusBarSpacer.getLayoutParams();
|
||||
params.height = statusBarHeight;
|
||||
statusBarSpacer.setLayoutParams(params);
|
||||
|
||||
Spinner spinnerType = view.findViewById(R.id.spinnerType);
|
||||
|
||||
ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(
|
||||
requireContext(), R.array.media_types, R.layout.item_spinner);
|
||||
spinnerAdapter.setDropDownViewResource(R.layout.item_spinner);
|
||||
// ✅ Aseguramos que el Spinner tenga las opciones
|
||||
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, new String[]{"Anime", "Manga"});
|
||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinnerType.setAdapter(spinnerAdapter);
|
||||
|
||||
|
||||
loadSampleData();
|
||||
showSections(animeList);
|
||||
|
||||
spinnerType.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(android.widget.AdapterView<?> parent, View view, int position, long id) {
|
||||
String selected = spinnerType.getSelectedItem().toString();
|
||||
if (selected.equals("Anime")) {
|
||||
showSections(animeList);
|
||||
} else {
|
||||
showSections(mangaList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(android.widget.AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
|
||||
editTextSearch.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) {
|
||||
String selected = spinnerType.getSelectedItem().toString();
|
||||
if (selected.equals("Anime")) {
|
||||
showSections(animeList, s.toString());
|
||||
} else {
|
||||
showSections(mangaList, s.toString());
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
handler.removeCallbacks(searchRunnable);
|
||||
}
|
||||
@Override public void afterTextChanged(Editable s) {
|
||||
searchRunnable = () -> performSearch(s.toString());
|
||||
handler.postDelayed(searchRunnable, 500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showSections(List<ItemModel> source) {
|
||||
showSections(source, "");
|
||||
}
|
||||
|
||||
private void showSections(List<ItemModel> source, String query) {
|
||||
sectionContainer.removeAllViews();
|
||||
|
||||
List<ItemModel> trending = new ArrayList<>();
|
||||
List<ItemModel> popular = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < source.size(); i++) {
|
||||
ItemModel item = source.get(i);
|
||||
if (!query.isEmpty() && !item.getTitle().toLowerCase().contains(query.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
if (i % 2 == 0) trending.add(item);
|
||||
else popular.add(item);
|
||||
}
|
||||
|
||||
if (!trending.isEmpty()) {
|
||||
addSection("Trending Now", trending);
|
||||
}
|
||||
|
||||
if (!popular.isEmpty()) {
|
||||
addSection("Popular This Season", popular);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSection(String title, List<ItemModel> items) {
|
||||
Context context = requireContext();
|
||||
|
||||
LinearLayout sectionLayout = new LinearLayout(context);
|
||||
sectionLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
sectionLayout.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
sectionLayout.setPadding(0, 0, 0, 24);
|
||||
|
||||
TextView titleView = new TextView(context);
|
||||
titleView.setText(title);
|
||||
titleView.setTextSize(18);
|
||||
titleView.setTypeface(null, Typeface.BOLD);
|
||||
titleView.setTextColor(ContextCompat.getColor(context, R.color.textPrimary));
|
||||
titleView.setPadding(0, 0, 0, 8);
|
||||
sectionLayout.addView(titleView);
|
||||
|
||||
RecyclerView recyclerView = new RecyclerView(context);
|
||||
|
||||
// 🔥 Establecer altura fija para 2 filas (170dp + 12sp de texto aprox + márgenes)
|
||||
int itemHeightPx = (int) (170 * context.getResources().getDisplayMetrics().density);
|
||||
int textHeightPx = (int) (40 * context.getResources().getDisplayMetrics().density);
|
||||
int totalHeight = (itemHeightPx + textHeightPx + 45) * 2;
|
||||
|
||||
|
||||
recyclerView.setLayoutParams(new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, totalHeight)); // <- altura calculada
|
||||
|
||||
GridLayoutManager layoutManager = new GridLayoutManager(context, 2, RecyclerView.HORIZONTAL, false);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
recyclerView.setAdapter(new BrowseGridAdapter(items));
|
||||
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
recyclerView.setClipToPadding(false);
|
||||
|
||||
sectionLayout.addView(recyclerView);
|
||||
sectionContainer.addView(sectionLayout);
|
||||
}
|
||||
|
||||
private void loadSampleData() {
|
||||
animeList.clear();
|
||||
mangaList.clear();
|
||||
|
||||
for (int i = 1; i <= 20; i++) {
|
||||
animeList.add(new ItemModel("Anime " + i, i + "/24", "https://example.com/anime" + i + ".jpg", ItemModel.ContentType.ANIME));
|
||||
mangaList.add(new ItemModel("Manga " + i, i + "/120", "https://example.com/manga" + i + ".jpg", ItemModel.ContentType.MANGA));
|
||||
}
|
||||
// Aquí continúa tu lógica previa, sin alterarse.
|
||||
}
|
||||
|
||||
private int getStatusBarHeight() {
|
||||
int result = 0;
|
||||
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
return resourceId > 0 ? getResources().getDimensionPixelSize(resourceId) : 0;
|
||||
}
|
||||
|
||||
private void performSearch(String query) {
|
||||
if (query.trim().isEmpty()) return;
|
||||
|
||||
Object selected = spinnerType.getSelectedItem();
|
||||
if (selected == null) return;
|
||||
|
||||
String selectedType = selected.toString();
|
||||
String type = selectedType.equalsIgnoreCase("Manga") ? "MANGA" : "ANIME";
|
||||
|
||||
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||
apiService.searchAniList(query, type).enqueue(new retrofit2.Callback<List<AniListMedia>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<AniListMedia>> call, Response<List<AniListMedia>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
searchAdapter = new AniListSearchAdapter(getContext(), response.body(), type);
|
||||
recyclerViewResults.setAdapter(searchAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<AniListMedia>> call, Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,20 @@
|
|||
// FragmentHome.java
|
||||
package com.santiparra.yomitrack.ui.fragments.home;
|
||||
|
||||
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.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -10,108 +22,340 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.gson.JsonObject;
|
||||
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.model.CommentDialog;
|
||||
import com.santiparra.yomitrack.model.CommentModel;
|
||||
import com.santiparra.yomitrack.model.ItemModel;
|
||||
import com.santiparra.yomitrack.model.RecentActivityModel;
|
||||
import com.santiparra.yomitrack.model.adapters.recentactivity_adapter.RecentActivityAdapter;
|
||||
import com.santiparra.yomitrack.model.adapters.sectionadapter.SectionAdapter;
|
||||
import com.santiparra.yomitrack.model.adapters.homeadapter.HomeCardAdapter;
|
||||
import com.santiparra.yomitrack.ui.fragments.editanime.EditAnimeFragment;
|
||||
import com.santiparra.yomitrack.ui.fragments.editmanga.EditMangaFragment;
|
||||
import com.santiparra.yomitrack.utils.ActivityLog;
|
||||
import com.santiparra.yomitrack.utils.DateUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Fragmento principal que muestra secciones de anime/manga y actividad reciente.
|
||||
*/
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class FragmentHome extends Fragment {
|
||||
|
||||
private final List<RecentActivityModel> fullRecentActivity = new ArrayList<>();
|
||||
private final List<RecentActivityModel> visibleRecentActivity = new ArrayList<>();
|
||||
private RecentActivityAdapter activityAdapter;
|
||||
private LinearLayout activityContainer;
|
||||
private EditText inputStatus;
|
||||
private Button btnPost;
|
||||
private RecyclerView recyclerAnime, recyclerManga;
|
||||
private ApiService api;
|
||||
private int userId;
|
||||
private String username;
|
||||
|
||||
public FragmentHome() {
|
||||
super(R.layout.fragment_home);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_home, container, false);
|
||||
|
||||
// region Secciones de contenido (Airing, En progreso...)
|
||||
RecyclerView mainRecyclerView = view.findViewById(R.id.mainRecyclerView);
|
||||
mainRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
activityContainer = view.findViewById(R.id.activityContainer);
|
||||
inputStatus = view.findViewById(R.id.inputStatus);
|
||||
btnPost = view.findViewById(R.id.btnPost);
|
||||
recyclerAnime = view.findViewById(R.id.recyclerAnime);
|
||||
recyclerManga = view.findViewById(R.id.recyclerManga);
|
||||
|
||||
List<String> sectionTitles = Arrays.asList("Airing", "Anime in Progress", "Manga in Progress");
|
||||
Map<String, List<ItemModel>> sectionItems = new HashMap<>();
|
||||
SharedPreferences prefs = requireContext().getSharedPreferences("user_session", Context.MODE_PRIVATE);
|
||||
userId = prefs.getInt("user_id", -1);
|
||||
username = prefs.getString("username", "Usuario");
|
||||
|
||||
// Datos simulados de ejemplo
|
||||
sectionItems.put("Airing", Arrays.asList(
|
||||
new ItemModel("Naruto", "5/220", "https://i.imgur.com/qzWZbL2.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("Bleach", "100/366", "https://i.imgur.com/I0d1HyA.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("One Piece", "900/1100", "https://i.imgur.com/VgVfG6K.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("Boruto", "10/100", "https://i.imgur.com/lWhD6Zc.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("Dragon Ball", "80/150", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("Another", "2/12", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME)
|
||||
));
|
||||
if (userId == -1) return view;
|
||||
|
||||
sectionItems.put("Anime in Progress", Arrays.asList(
|
||||
new ItemModel("Attack on Titan", "16/25", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("Jujutsu Kaisen", "10/24", "https://i.imgur.com/lWhD6Zc.jpg", ItemModel.ContentType.ANIME),
|
||||
new ItemModel("One Piece", "900/1100", "https://i.imgur.com/VgVfG6K.jpg", ItemModel.ContentType.ANIME)
|
||||
));
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
sectionItems.put("Manga in Progress", Arrays.asList(
|
||||
new ItemModel("Chainsaw Man", "45/100", "https://i.imgur.com/7tZ0h8R.jpg", ItemModel.ContentType.MANGA),
|
||||
new ItemModel("Berserk", "370/380", "https://i.imgur.com/8FJYYHo.jpg", ItemModel.ContentType.MANGA)
|
||||
));
|
||||
btnPost.setOnClickListener(v -> postThought());
|
||||
|
||||
SectionAdapter sectionAdapter = new SectionAdapter(sectionTitles, sectionItems);
|
||||
mainRecyclerView.setAdapter(sectionAdapter);
|
||||
// endregion
|
||||
loadAnimeSection();
|
||||
loadMangaSection();
|
||||
loadActivity();
|
||||
return view;
|
||||
}
|
||||
|
||||
// region Actividad reciente
|
||||
RecyclerView activityRecyclerView = view.findViewById(R.id.activityRecyclerView);
|
||||
activityRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
private void loadAnimeSection() {
|
||||
api.getAnimeByUserAndStatus(userId, "Watching").enqueue(new Callback<List<AnimeEntity>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<AnimeEntity>> call, Response<List<AnimeEntity>> response) {
|
||||
if (!isAdded()) return;
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
List<ItemModel> items = new ArrayList<>();
|
||||
for (AnimeEntity anime : response.body()) {
|
||||
items.add(new ItemModel(anime.getTitle(), anime.getProgress() + "/" + anime.getTotalEpisodes(), anime.getImageUrl(), ItemModel.ContentType.ANIME, anime));
|
||||
}
|
||||
HomeCardAdapter adapter = new HomeCardAdapter(items, item -> {
|
||||
EditAnimeFragment fragment = new EditAnimeFragment((AnimeEntity) item.getObject());
|
||||
requireActivity().getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.frame_layout, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
});
|
||||
recyclerAnime.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
recyclerAnime.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
fullRecentActivity.addAll(Arrays.asList(
|
||||
//new RecentActivityModel("Midca", "Read chapters 1 - 60 of", "Choujun! Choujou Senpai", "4 minutes ago", "https://i.imgur.com/7tZ0h8R.jpg"),
|
||||
//new RecentActivityModel("prtrncyon", "Scored 9/10 on", "Chainsaw Man", "12 hours ago", "https://cdn.myanimelist.net/images/manga/2/253146.jpg")
|
||||
// ... más datos simulados aquí
|
||||
));
|
||||
@Override
|
||||
public void onFailure(Call<List<AnimeEntity>> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
|
||||
visibleRecentActivity.addAll(fullRecentActivity.subList(0, Math.min(10, fullRecentActivity.size())));
|
||||
activityAdapter = new RecentActivityAdapter(visibleRecentActivity);
|
||||
activityRecyclerView.setAdapter(activityAdapter);
|
||||
private void loadMangaSection() {
|
||||
api.getMangaByUserAndStatus(userId, "Reading").enqueue(new Callback<List<MangaEntity>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<MangaEntity>> call, Response<List<MangaEntity>> response) {
|
||||
if (!isAdded()) return;
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
List<ItemModel> items = new ArrayList<>();
|
||||
for (MangaEntity manga : response.body()) {
|
||||
items.add(new ItemModel(manga.getTitle(), manga.getProgress() + "/" + manga.getTotalChapters(), manga.getImageUrl(), ItemModel.ContentType.MANGA, manga));
|
||||
}
|
||||
HomeCardAdapter adapter = new HomeCardAdapter(items, item -> {
|
||||
EditMangaFragment fragment = new EditMangaFragment((MangaEntity) item.getObject());
|
||||
requireActivity().getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.frame_layout, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
});
|
||||
recyclerManga.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||
recyclerManga.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
Button buttonShowMore = view.findViewById(R.id.buttonShowMoreActivity);
|
||||
Button buttonShowLess = view.findViewById(R.id.buttonShowLessActivity);
|
||||
@Override
|
||||
public void onFailure(Call<List<MangaEntity>> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Mostrar más/menos actividad
|
||||
if (fullRecentActivity.size() > 10) {
|
||||
buttonShowMore.setVisibility(View.VISIBLE);
|
||||
buttonShowLess.setVisibility(View.GONE);
|
||||
private JsonObject createLikeJson(int userId, int targetId) {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("userId", userId);
|
||||
body.addProperty("activityId", targetId);
|
||||
return body;
|
||||
}
|
||||
|
||||
buttonShowMore.setOnClickListener(v -> {
|
||||
visibleRecentActivity.clear();
|
||||
visibleRecentActivity.addAll(fullRecentActivity);
|
||||
activityAdapter.notifyDataSetChanged();
|
||||
buttonShowMore.setVisibility(View.GONE);
|
||||
buttonShowLess.setVisibility(View.VISIBLE);
|
||||
private void actualizarCorazon(ImageButton button, boolean liked) {
|
||||
button.setImageResource(liked ? R.drawable.ic_heart_filled : R.drawable.ic_heart_outline);
|
||||
button.setColorFilter(requireContext().getColor(liked ? R.color.pink : R.color.gray));
|
||||
}
|
||||
|
||||
private void postThought() {
|
||||
String status = inputStatus.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(status)) {
|
||||
Toast.makeText(getContext(), "Escribe algo", 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 (!isAdded()) return;
|
||||
if (response.isSuccessful()) {
|
||||
inputStatus.setText("");
|
||||
loadActivity();
|
||||
Toast.makeText(getContext(), "Publicado", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
if (!isAdded()) return;
|
||||
Toast.makeText(getContext(), "Error al publicar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadActivity() {
|
||||
api.getActivityLog(userId).enqueue(new Callback<List<ActivityLog>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<ActivityLog>> call, Response<List<ActivityLog>> response) {
|
||||
if (!isAdded()) return;
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
activityContainer.removeAllViews();
|
||||
LayoutInflater inflater = LayoutInflater.from(requireContext());
|
||||
|
||||
for (ActivityLog log : response.body()) {
|
||||
View card = inflater.inflate(R.layout.item_activity_card, activityContainer, false);
|
||||
|
||||
LinearLayout commentsContainer = card.findViewById(R.id.commentsContainer);
|
||||
commentsContainer.setVisibility(View.GONE);
|
||||
|
||||
card.setOnClickListener(v -> {
|
||||
if (commentsContainer.getVisibility() == View.VISIBLE) {
|
||||
commentsContainer.animate().alpha(0).setDuration(150).withEndAction(() -> commentsContainer.setVisibility(View.GONE)).start();
|
||||
} else {
|
||||
commentsContainer.setAlpha(0);
|
||||
commentsContainer.setVisibility(View.VISIBLE);
|
||||
loadComments(log.getId(), commentsContainer);
|
||||
commentsContainer.animate().alpha(1).setDuration(150).start();
|
||||
}
|
||||
});
|
||||
|
||||
buttonShowLess.setOnClickListener(v -> {
|
||||
visibleRecentActivity.clear();
|
||||
visibleRecentActivity.addAll(fullRecentActivity.subList(0, 10));
|
||||
activityAdapter.notifyDataSetChanged();
|
||||
buttonShowMore.setVisibility(View.VISIBLE);
|
||||
buttonShowLess.setVisibility(View.GONE);
|
||||
((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(DateUtils.getRelativeTime(log.getTimestamp()));
|
||||
|
||||
ImageView coverImage = card.findViewById(R.id.activityCover);
|
||||
if (!TextUtils.isEmpty(log.getImageUrl())) {
|
||||
Glide.with(requireContext())
|
||||
.load(log.getImageUrl())
|
||||
.placeholder(R.drawable.placeholder_image)
|
||||
.error(R.drawable.placeholder_image)
|
||||
.into(coverImage);
|
||||
}
|
||||
|
||||
ImageButton commentButton = card.findViewById(R.id.commentButton);
|
||||
ImageButton likeButton = card.findViewById(R.id.likeButton);
|
||||
|
||||
commentButton.setOnClickListener(v -> {
|
||||
CommentDialog dialog = new CommentDialog(requireContext(), userId, log.getId(), () -> loadComments(log.getId(), commentsContainer));
|
||||
dialog.show();
|
||||
});
|
||||
|
||||
api.checkLike(userId, log.getId()).enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
final boolean[] isLiked = {response.body().get("liked").getAsBoolean()};
|
||||
actualizarCorazon(likeButton, isLiked[0]);
|
||||
|
||||
likeButton.setOnClickListener(v -> {
|
||||
if (isLiked[0]) {
|
||||
api.deleteLike(createLikeJson(userId, log.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful()) {
|
||||
isLiked[0] = false;
|
||||
actualizarCorazon(likeButton, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
} else {
|
||||
buttonShowMore.setVisibility(View.GONE);
|
||||
buttonShowLess.setVisibility(View.GONE);
|
||||
api.postLike(createLikeJson(userId, log.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful()) {
|
||||
isLiked[0] = true;
|
||||
actualizarCorazon(likeButton, true);
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
|
||||
activityContainer.addView(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<ActivityLog>> call, Throwable t) {
|
||||
if (!isAdded()) return;
|
||||
Toast.makeText(getContext(), "Error al cargar actividad", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadComments(int activityId, LinearLayout container) {
|
||||
api.getCommentsByActivity(activityId).enqueue(new Callback<List<CommentModel>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<CommentModel>> call, Response<List<CommentModel>> response) {
|
||||
if (!isAdded()) return;
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
container.removeAllViews();
|
||||
LayoutInflater inflater = LayoutInflater.from(requireContext());
|
||||
|
||||
for (CommentModel comment : response.body()) {
|
||||
View commentView = inflater.inflate(R.layout.item_comment, container, false);
|
||||
|
||||
TextView usernameView = commentView.findViewById(R.id.commentUsername);
|
||||
TextView commentText = commentView.findViewById(R.id.commentText);
|
||||
TextView dateView = commentView.findViewById(R.id.commentDate);
|
||||
ImageView avatar = commentView.findViewById(R.id.commentAvatar);
|
||||
ImageButton likeButton = commentView.findViewById(R.id.commentLikeButton);
|
||||
ImageButton replyButton = commentView.findViewById(R.id.replyButton);
|
||||
|
||||
usernameView.setText(comment.getUsername());
|
||||
commentText.setText(comment.getText());
|
||||
dateView.setText(DateUtils.getRelativeTime(comment.getCreatedAt()));
|
||||
|
||||
if (!TextUtils.isEmpty(comment.getAvatarUrl())) {
|
||||
Glide.with(requireContext())
|
||||
.load(comment.getAvatarUrl())
|
||||
.placeholder(R.drawable.rectangle_placeholder)
|
||||
.error(R.drawable.error_image)
|
||||
.into(avatar);
|
||||
}
|
||||
|
||||
likeButton.setImageResource(comment.isLiked() ? R.drawable.ic_heart_filled : R.drawable.ic_heart_outline);
|
||||
likeButton.setColorFilter(requireContext().getColor(comment.isLiked() ? R.color.pink : R.color.gray));
|
||||
|
||||
likeButton.setOnClickListener(v -> {
|
||||
boolean newLike = !comment.isLiked();
|
||||
comment.setLiked(newLike);
|
||||
actualizarCorazon(likeButton, newLike);
|
||||
if (newLike) {
|
||||
api.postLike(createLikeJson(userId, comment.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {}
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
} else {
|
||||
api.deleteLike(createLikeJson(userId, comment.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {}
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
replyButton.setOnClickListener(v -> {
|
||||
CommentDialog dialog = new CommentDialog(requireContext(), userId, activityId, () -> loadComments(activityId, container));
|
||||
dialog.show();
|
||||
});
|
||||
|
||||
container.addView(commentView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<CommentModel>> call, Throwable t) {
|
||||
if (!isAdded()) return;
|
||||
Toast.makeText(getContext(), "Error al cargar comentarios", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import com.santiparra.yomitrack.model.UserStatsResponse;
|
|||
import com.santiparra.yomitrack.utils.ActivityLog;
|
||||
import com.santiparra.yomitrack.utils.DateUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
|
@ -91,9 +90,6 @@ public class FragmentProfile extends Fragment {
|
|||
editBiography.setText(bioPrefs.getString(BIO_KEY, ""));
|
||||
|
||||
api = ApiClient.getClient().create(ApiService.class);
|
||||
|
||||
loadStats();
|
||||
loadActivity();
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
|
|
@ -122,24 +118,19 @@ public class FragmentProfile extends Fragment {
|
|||
|
||||
private void populateStats(LinearLayout container, Map<String, Integer> stats) {
|
||||
container.removeAllViews();
|
||||
|
||||
if (stats == null || stats.isEmpty()) {
|
||||
addTextToContainer(container, "No hay estadísticas disponibles");
|
||||
return;
|
||||
}
|
||||
|
||||
int total = stats.values().stream().mapToInt(Integer::intValue).sum();
|
||||
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);
|
||||
|
||||
label.setText(String.format(Locale.getDefault(), "%s • %d", entry.getKey(), entry.getValue()));
|
||||
bar.setProgress(total > 0 ? (entry.getValue() * 100 / total) : 0);
|
||||
bar.setProgressTintList(ColorStateList.valueOf(getColorForStatus(entry.getKey())));
|
||||
|
||||
container.addView(statView);
|
||||
}
|
||||
}
|
||||
|
|
@ -153,18 +144,12 @@ public class FragmentProfile extends Fragment {
|
|||
|
||||
private int getColorForStatus(String status) {
|
||||
switch (status.toLowerCase(Locale.ROOT)) {
|
||||
case "watching":
|
||||
return requireContext().getColor(R.color.status_watching);
|
||||
case "completed":
|
||||
return requireContext().getColor(R.color.status_completed);
|
||||
case "paused":
|
||||
return requireContext().getColor(R.color.status_paused);
|
||||
case "dropped":
|
||||
return requireContext().getColor(R.color.status_dropped);
|
||||
case "planning":
|
||||
return requireContext().getColor(R.color.status_planning);
|
||||
default:
|
||||
return requireContext().getColor(R.color.gray);
|
||||
case "watching": return requireContext().getColor(R.color.status_watching);
|
||||
case "completed": return requireContext().getColor(R.color.status_completed);
|
||||
case "paused": return requireContext().getColor(R.color.status_paused);
|
||||
case "dropped": return requireContext().getColor(R.color.status_dropped);
|
||||
case "planning": return requireContext().getColor(R.color.status_planning);
|
||||
default: return requireContext().getColor(R.color.gray);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,19 +160,14 @@ public class FragmentProfile extends Fragment {
|
|||
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);
|
||||
|
||||
LinearLayout commentsContainer = card.findViewById(R.id.commentsContainer);
|
||||
|
||||
commentsContainer.setVisibility(View.GONE);
|
||||
|
||||
card.setOnClickListener(v -> {
|
||||
if (commentsContainer.getVisibility() == View.VISIBLE) {
|
||||
commentsContainer.animate().alpha(0).setDuration(150).withEndAction(() -> {
|
||||
commentsContainer.setVisibility(View.GONE);
|
||||
}).start();
|
||||
commentsContainer.animate().alpha(0).setDuration(150).withEndAction(() -> commentsContainer.setVisibility(View.GONE)).start();
|
||||
} else {
|
||||
commentsContainer.setAlpha(0);
|
||||
commentsContainer.setVisibility(View.VISIBLE);
|
||||
|
|
@ -203,20 +183,14 @@ public class FragmentProfile extends Fragment {
|
|||
|
||||
ImageView coverImage = card.findViewById(R.id.activityCover);
|
||||
if (!TextUtils.isEmpty(log.getImageUrl())) {
|
||||
Glide.with(requireContext())
|
||||
.load(log.getImageUrl())
|
||||
.placeholder(R.drawable.placeholder_image)
|
||||
.error(R.drawable.placeholder_image)
|
||||
.into(coverImage);
|
||||
Glide.with(requireContext()).load(log.getImageUrl()).placeholder(R.drawable.placeholder_image).error(R.drawable.placeholder_image).into(coverImage);
|
||||
}
|
||||
|
||||
ImageButton commentButton = card.findViewById(R.id.commentButton);
|
||||
ImageButton likeButton = card.findViewById(R.id.likeButton);
|
||||
|
||||
commentButton.setOnClickListener(v -> {
|
||||
CommentDialog dialog = new CommentDialog(requireContext(), userId, log.getId(), () -> {
|
||||
loadComments(log.getId(), card.findViewById(R.id.commentsContainer));
|
||||
});
|
||||
CommentDialog dialog = new CommentDialog(requireContext(), userId, log.getId(), () -> loadComments(log.getId(), commentsContainer));
|
||||
dialog.show();
|
||||
});
|
||||
|
||||
|
|
@ -226,47 +200,25 @@ public class FragmentProfile extends Fragment {
|
|||
if (response.isSuccessful() && response.body() != null) {
|
||||
final boolean[] isLiked = {response.body().get("liked").getAsBoolean()};
|
||||
actualizarCorazon(likeButton, isLiked[0]);
|
||||
|
||||
likeButton.setOnClickListener(v -> {
|
||||
if (isLiked[0]) {
|
||||
api.deleteLike(createLikeJson(userId, log.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful()) {
|
||||
isLiked[0] = false;
|
||||
actualizarCorazon(likeButton, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error de conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
boolean newLike = !isLiked[0];
|
||||
isLiked[0] = newLike;
|
||||
if (newLike) {
|
||||
api.postLike(createLikeJson(userId, log.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) { actualizarCorazon(likeButton, true); }
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
} else {
|
||||
api.postLike(createLikeJson(userId, log.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful()) {
|
||||
isLiked[0] = true;
|
||||
actualizarCorazon(likeButton, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error de conexión", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
api.deleteLike(createLikeJson(userId, log.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) { actualizarCorazon(likeButton, false); }
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error al verificar like", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
|
||||
activityContainer.addView(card);
|
||||
|
|
@ -287,24 +239,19 @@ public class FragmentProfile extends Fragment {
|
|||
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) {
|
||||
@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) {
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error al publicar", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
|
@ -312,61 +259,78 @@ public class FragmentProfile extends Fragment {
|
|||
|
||||
private void loadComments(int activityId, LinearLayout container) {
|
||||
api.getCommentsByActivity(activityId).enqueue(new Callback<List<CommentModel>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<CommentModel>> call, Response<List<CommentModel>> response) {
|
||||
@Override public void onResponse(Call<List<CommentModel>> call, Response<List<CommentModel>> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
container.removeAllViews();
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
for (CommentModel comment : response.body()) {
|
||||
View commentView = LayoutInflater.from(getContext())
|
||||
.inflate(R.layout.item_comment, container, false);
|
||||
|
||||
TextView usernameView = commentView.findViewById(R.id.commentUsername);
|
||||
TextView commentText = commentView.findViewById(R.id.commentText);
|
||||
TextView dateView = commentView.findViewById(R.id.commentDate);
|
||||
ImageView avatar = commentView.findViewById(R.id.commentAvatar);
|
||||
|
||||
usernameView.setText(comment.getUsername());
|
||||
commentText.setText(comment.getText());
|
||||
dateView.setText(DateUtils.getRelativeTime(comment.getCreatedAt())); // usa tu util
|
||||
|
||||
View view = inflater.inflate(R.layout.item_comment, container, false);
|
||||
((TextView) view.findViewById(R.id.commentUsername)).setText(comment.getUsername());
|
||||
((TextView) view.findViewById(R.id.commentText)).setText(comment.getText());
|
||||
((TextView) view.findViewById(R.id.commentDate)).setText(DateUtils.getRelativeTime(comment.getCreatedAt()));
|
||||
ImageView avatar = view.findViewById(R.id.commentAvatar);
|
||||
if (!TextUtils.isEmpty(comment.getAvatarUrl())) {
|
||||
Glide.with(getContext())
|
||||
.load(comment.getAvatarUrl())
|
||||
.placeholder(R.drawable.rectangle_placeholder)
|
||||
.error(R.drawable.error_image)
|
||||
.into(avatar);
|
||||
Glide.with(requireContext()).load(comment.getAvatarUrl()).placeholder(R.drawable.rectangle_placeholder).error(R.drawable.error_image).into(avatar);
|
||||
}
|
||||
|
||||
container.addView(commentView);
|
||||
}
|
||||
ImageButton replyButton = view.findViewById(R.id.replyButton);
|
||||
replyButton.setOnClickListener(v -> {
|
||||
CommentDialog dialog = new CommentDialog(requireContext(), userId, activityId, () -> loadComments(activityId, container), comment.getUsername());
|
||||
dialog.show();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
ImageButton likeButton = view.findViewById(R.id.commentLikeButton);
|
||||
api.checkLike(userId, comment.getId()).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
final boolean[] isLiked = {response.body().get("liked").getAsBoolean()};
|
||||
actualizarCorazon(likeButton, isLiked[0]);
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<List<CommentModel>> call, Throwable t) {
|
||||
likeButton.setOnClickListener(v -> {
|
||||
boolean newLike = !isLiked[0];
|
||||
isLiked[0] = newLike;
|
||||
|
||||
if (newLike) {
|
||||
api.postLike(createLikeJson(userId, comment.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
actualizarCorazon(likeButton, true);
|
||||
}
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
} else {
|
||||
api.deleteLike(createLikeJson(userId, comment.getId())).enqueue(new Callback<JsonObject>() {
|
||||
@Override public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
actualizarCorazon(likeButton, false);
|
||||
}
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@Override public void onFailure(Call<JsonObject> call, Throwable t) {}
|
||||
});
|
||||
|
||||
container.addView(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override public void onFailure(Call<List<CommentModel>> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Error al cargar comentarios", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private JsonObject createLikeJson(int userId, int activityId) {
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("userId", userId);
|
||||
body.addProperty("activityId", activityId);
|
||||
return body;
|
||||
private JsonObject createLikeJson(int userId, int targetId) {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("userId", userId);
|
||||
json.addProperty("commentId", targetId);
|
||||
return json;
|
||||
}
|
||||
|
||||
private void actualizarCorazon(ImageButton likeButton, boolean liked) {
|
||||
if (liked) {
|
||||
likeButton.setImageResource(R.drawable.ic_heart_filled);
|
||||
likeButton.setColorFilter(requireContext().getColor(R.color.pink));
|
||||
} else {
|
||||
likeButton.setImageResource(R.drawable.ic_heart_outline);
|
||||
likeButton.setColorFilter(requireContext().getColor(R.color.gray));
|
||||
}
|
||||
private void actualizarCorazon(ImageButton btn, boolean liked) {
|
||||
btn.setImageResource(liked ? R.drawable.ic_heart_filled : R.drawable.ic_heart_outline);
|
||||
btn.setColorFilter(requireContext().getColor(liked ? R.color.pink : R.color.gray));
|
||||
}
|
||||
|
||||
private void saveBiography() {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ public class ActivityLog {
|
|||
|
||||
@SerializedName("id")
|
||||
private int id;
|
||||
|
||||
@SerializedName("userId")
|
||||
private int userId;
|
||||
|
||||
@SerializedName("username")
|
||||
private String username;
|
||||
|
||||
@SerializedName("action")
|
||||
private String action;
|
||||
|
||||
|
|
@ -22,6 +29,14 @@ public class ActivityLog {
|
|||
return id;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,4 +59,10 @@ public class DateUtils {
|
|||
return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
|
||||
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
|
||||
public static String getCurrentTimestamp() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,20 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:padding="16dp"
|
||||
android:id="@+id/commentDialogLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="?android:attr/windowBackground">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/commentInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Escribe tu comentario" />
|
||||
android:hint="Escribe tu comentario..."
|
||||
android:minHeight="80dp"
|
||||
android:gravity="top|start"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLines="5"
|
||||
android:background="@color/primary"
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textColorHint="@color/textPrimary"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/sendComment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Enviar"
|
||||
android:textAllCaps="false"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"/>
|
||||
android:layout_marginTop="12dp"
|
||||
android:backgroundTint="@color/primary"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -1,69 +1,72 @@
|
|||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/scrollView"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:fitsSystemWindows="true"
|
||||
android:background="@color/background"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Espaciador reducido -->
|
||||
<View
|
||||
android:id="@+id/statusBarSpacer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="12dp" />
|
||||
|
||||
<!-- Encabezado -->
|
||||
<!-- Título y spinner -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="75dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewBrowse"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Browse"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:layout_marginEnd="8dp" />
|
||||
android:textSize="24sp"
|
||||
android:textColor="@android:color/white"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/primary" />
|
||||
android:backgroundTint="@android:color/white"
|
||||
android:popupBackground="@color/primary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Buscador -->
|
||||
<EditText
|
||||
android:id="@+id/editTextSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:hint="Search"
|
||||
android:drawableStart="@android:drawable/ic_menu_search"
|
||||
android:background="@drawable/edittext_background"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textColorHint="@color/textPrimary" />
|
||||
|
||||
<!-- Contenedor de secciones -->
|
||||
<!-- Caja de búsqueda -->
|
||||
<LinearLayout
|
||||
android:id="@+id/sectionContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="16dp" />
|
||||
android:background="@drawable/bg_search_box"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:padding="12dp">
|
||||
|
||||
<ImageView
|
||||
android:src="@android:drawable/ic_menu_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:tint="@android:color/darker_gray" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextSearch"
|
||||
android:hint="Buscar..."
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="8dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColorHint="@android:color/white"
|
||||
android:background="@android:color/transparent"/>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<!-- Resultados -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerViewResults"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_weight="1"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="16dp"/>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -1,39 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView 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"
|
||||
tools:context=".ui.fragments.home.FragmentHome">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="80dp"
|
||||
android:paddingBottom="100dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/mainRecyclerView"
|
||||
<!-- Sección Anime en progreso -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:contentDescription="@string/home_section_list"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:overScrollMode="never"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp" />
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Watching"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textPrimary" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerAnime"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:orientation="horizontal" />
|
||||
|
||||
<!-- Sección Manga en progreso -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Reading"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/textPrimary" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerManga"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:orientation="horizontal" />
|
||||
|
||||
<!-- EditText para estado -->
|
||||
<EditText
|
||||
android:id="@+id/editStatus"
|
||||
android:id="@+id/inputStatus"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
|
|
@ -46,6 +69,18 @@
|
|||
android:textColorHint="@color/textPrimary"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<!-- Botón publicar -->
|
||||
<Button
|
||||
android:id="@+id/btnPost"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Publicar"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Actividad reciente -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -56,35 +91,12 @@
|
|||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/activityRecyclerView"
|
||||
<LinearLayout
|
||||
android:id="@+id/activityContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonShowMoreActivity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="Mostrar más"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonShowLessActivity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="Mostrar menos"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</FrameLayout>
|
||||
</ScrollView>
|
||||
|
|
|
|||
|
|
@ -4,66 +4,81 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp"
|
||||
android:gravity="top"
|
||||
android:background="@color/primary">
|
||||
|
||||
<!-- Avatar del usuario -->
|
||||
<ImageView
|
||||
android:id="@+id/commentAvatar"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:src="@drawable/ic_profile"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/circle_mask" />
|
||||
android:background="@drawable/circle_mask"
|
||||
android:clipToOutline="true" />
|
||||
|
||||
<!-- Contenido del comentario -->
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Nombre del usuario -->
|
||||
<TextView
|
||||
android:id="@+id/commentUsername"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Username"
|
||||
android:text="Usuario"
|
||||
android:textStyle="bold"
|
||||
android:textSize="13sp" />
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<!-- Texto del comentario -->
|
||||
<TextView
|
||||
android:id="@+id/commentText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Comentario aquí"
|
||||
android:text="Comentario de prueba"
|
||||
android:textColor="@color/textPrimary"
|
||||
android:textSize="14sp"
|
||||
android:lineSpacingExtra="2dp"
|
||||
android:maxLines="5"
|
||||
android:ellipsize="end"
|
||||
android:paddingEnd="8dp" />
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginBottom="2dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<!-- Fecha -->
|
||||
<TextView
|
||||
android:id="@+id/commentDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="hace 5 min"
|
||||
android:textSize="11sp"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/gray" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Botón de like -->
|
||||
<ImageButton
|
||||
android:id="@+id/commentLikeButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:src="@drawable/ic_heart"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/like_comment"
|
||||
app:tint="@color/gray" />
|
||||
|
||||
<!-- Botón opcional para responder -->
|
||||
<ImageButton
|
||||
android:id="@+id/replyButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:src="@drawable/ic_reply"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="Responder comentario"
|
||||
app:tint="@color/gray" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -56,4 +56,8 @@
|
|||
<item name="commentButton" type="id" />
|
||||
<item name="likeButton" type="id" />
|
||||
<item name="activityCover" type="id" />
|
||||
<item name="itemTitle" type="id" />
|
||||
<item name="btnAdd" type="id" />
|
||||
<item name="itemImage" type="id" />
|
||||
<item name="commentDialogLayout" type="id" />
|
||||
</resources>
|
||||
Loading…
Reference in New Issue