170 lines
7.8 KiB
Java
170 lines
7.8 KiB
Java
|
|
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!");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|