JetChat/src/main/java/com/lotus_lab/jetchat/ui/ChatAdapter.java

170 lines
7.8 KiB
Java
Raw Normal View History

2025-05-07 16:38:58 +08:00
package com.lotus_lab.jetchat.ui;
import android.util.Log; // Import Log
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.lotus_lab.jetchat.R;
import com.lotus_lab.jetchat.data.ChatMessage; // 确保 ChatMessage 有 role 属性
import java.util.ArrayList;
import java.util.List;
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.MessageViewHolder> {
private static final String ADAPTER_TAG = "ChatAdapter"; // Tag for logging
private final List<ChatMessage> messages;
// 在 ChatMessage 类中定义这些常量,或者在这里定义,以避免硬编码字符串 "assistant" 和 "user"
// public static final String ROLE_USER = "user";
// public static final String ROLE_ASSISTANT = "assistant";
public ChatAdapter(List<ChatMessage> initialMessages) {
this.messages = new ArrayList<>(initialMessages);
}
public void clearMessages() {
int oldSize = messages.size();
this.messages.clear();
notifyItemRangeRemoved(0, oldSize);
Log.d(ADAPTER_TAG, "Messages cleared. Old size: " + oldSize);
}
public List<ChatMessage> getMessages() {
return new ArrayList<>(this.messages); // Return a copy
}
public void setMessages(List<ChatMessage> newMessages) {
this.messages.clear();
if (newMessages != null) { // Add null check for safety
this.messages.addAll(newMessages);
}
notifyDataSetChanged(); // Consider using DiffUtil for better performance in production
Log.d(ADAPTER_TAG, "Messages set. New count: " + this.messages.size());
}
public void addMessage(ChatMessage message) {
if (message == null) {
Log.w(ADAPTER_TAG, "Attempted to add a null message.");
return;
}
this.messages.add(message);
notifyItemInserted(messages.size() - 1);
Log.d(ADAPTER_TAG, "Message added. Role: " + (message.role != null ? message.role : "null") +
", Content: '" + (message.content != null ? message.content : "null") +
"'. New count: " + messages.size());
}
@NonNull
@Override
public MessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
Log.d(ADAPTER_TAG, "onCreateViewHolder called for viewType: " + viewType);
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message, parent, false);
return new MessageViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MessageViewHolder holder, int position) {
ChatMessage message = messages.get(position);
Log.i(ADAPTER_TAG, "-----------------------------------------------------");
Log.i(ADAPTER_TAG, "onBindViewHolder - Position: " + position);
if (message == null) {
Log.e(ADAPTER_TAG, "Message object is NULL at position " + position + ". Hiding item.");
holder.itemView.setVisibility(View.GONE); // Hide the item if message is null
return;
}
// Log the raw role and content from the ChatMessage object
Log.d(ADAPTER_TAG, "Raw Message Role: '" + message.role + "'");
Log.d(ADAPTER_TAG, "Raw Message Content: '" + message.content + "'");
if (message.role == null || message.content == null) {
holder.itemView.setVisibility(View.GONE);
Log.w(ADAPTER_TAG, "Message role or content is null at position " + position + ". Role: '" + message.role + "', Content: '" + message.content + "'. Hiding item.");
return;
}
// Ensure item is visible if data is valid
holder.itemView.setVisibility(View.VISIBLE);
// Optional: Reset item background if you were setting alternating colors for the whole item in debug
// holder.itemView.setBackground(null);
// Crucial check: compare role with "assistant" and "user"
// Make sure these strings EXACTLY match what's in your ChatMessage.role
boolean isAiMessage = "assistant".equals(message.role);
// boolean isUserMessage = "user".equals(message.role); // You can also explicitly check for user
Log.d(ADAPTER_TAG, "Processed Role: '" + message.role + "', isAiMessage = " + isAiMessage);
holder.tvMessage.setText(message.content);
holder.tvMessage.setVisibility(View.VISIBLE); // Ensure TextView is visible
// Reset text color and background to defaults from XML or a base style,
// in case previous debug styles are cached by RecyclerView's ViewHolder.
holder.tvMessage.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), android.R.color.black)); // Or your R.color.your_default_text_color
// holder.tvMessage.setBackground(null); // Let specific backgrounds below take precedence
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) holder.tvMessage.getLayoutParams();
if (isAiMessage) {
Log.d(ADAPTER_TAG, "Applying AI message style for: '" + message.content.substring(0, Math.min(message.content.length(), 20)) + "...'");
holder.ivAiAvatar.setVisibility(View.VISIBLE);
holder.ivUserAvatar.setVisibility(View.GONE);
params.horizontalBias = 0.0f; // AI 消息靠左
holder.tvMessage.setBackground(
ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.bg_reply_message_bubble)
);
// Example: Different text color for AI messages if needed
// holder.tvMessage.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.ai_text_color));
} else { // Assuming any non-AI message is a user message for now
// If you have other roles like "system", you'll need more specific checks.
Log.d(ADAPTER_TAG, "Applying User message style for: '" + message.content.substring(0, Math.min(message.content.length(), 20)) + "...'");
holder.ivAiAvatar.setVisibility(View.GONE);
holder.ivUserAvatar.setVisibility(View.GONE); // As per your item_message.xml, user avatar is GONE by default
params.horizontalBias = 1.0f; // 用户消息靠右
holder.tvMessage.setBackground(
ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.bg_user_message_bubble)
);
// Example: Different text color for user messages if needed
// holder.tvMessage.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.user_text_color));
}
holder.tvMessage.setLayoutParams(params);
Log.i(ADAPTER_TAG, "Finished applying style for position: " + position);
Log.i(ADAPTER_TAG, "-----------------------------------------------------");
}
@Override
public int getItemCount() {
return messages.size();
}
static class MessageViewHolder extends RecyclerView.ViewHolder {
ImageView ivAiAvatar;
ImageView ivUserAvatar;
TextView tvMessage;
MessageViewHolder(@NonNull View itemView) {
super(itemView);
ivAiAvatar = itemView.findViewById(R.id.iv_ai_avatar);
ivUserAvatar = itemView.findViewById(R.id.iv_user_avatar);
tvMessage = itemView.findViewById(R.id.tv_message);
if (ivAiAvatar == null) Log.e(ADAPTER_TAG, "MessageViewHolder: ivAiAvatar is null!");
if (ivUserAvatar == null) Log.e(ADAPTER_TAG, "MessageViewHolder: ivUserAvatar is null!");
if (tvMessage == null) Log.e(ADAPTER_TAG, "MessageViewHolder: tvMessage is null!");
}
}
}