made it so we can put attachments to chat
- Sending not implemented until backend is complete
This commit is contained in:
@@ -22,6 +22,15 @@ public class MessageDTO {
|
|||||||
@SerializedName("isRead")
|
@SerializedName("isRead")
|
||||||
private Boolean isRead;
|
private Boolean isRead;
|
||||||
|
|
||||||
|
@SerializedName("attachmentUrl")
|
||||||
|
private String attachmentUrl;
|
||||||
|
|
||||||
|
@SerializedName("attachmentName")
|
||||||
|
private String attachmentName;
|
||||||
|
|
||||||
|
@SerializedName("attachmentType")
|
||||||
|
private String attachmentType;
|
||||||
|
|
||||||
public MessageDTO() {}
|
public MessageDTO() {}
|
||||||
|
|
||||||
public Long getId() { return id; }
|
public Long getId() { return id; }
|
||||||
@@ -41,4 +50,13 @@ public class MessageDTO {
|
|||||||
|
|
||||||
public Boolean getIsRead() { return isRead; }
|
public Boolean getIsRead() { return isRead; }
|
||||||
public void setIsRead(Boolean isRead) { this.isRead = isRead; }
|
public void setIsRead(Boolean isRead) { this.isRead = isRead; }
|
||||||
|
|
||||||
|
public String getAttachmentUrl() { return attachmentUrl; }
|
||||||
|
public void setAttachmentUrl(String attachmentUrl) { this.attachmentUrl = attachmentUrl; }
|
||||||
|
|
||||||
|
public String getAttachmentName() { return attachmentName; }
|
||||||
|
public void setAttachmentName(String attachmentName) { this.attachmentName = attachmentName; }
|
||||||
|
|
||||||
|
public String getAttachmentType() { return attachmentType; }
|
||||||
|
public void setAttachmentType(String attachmentType) { this.attachmentType = attachmentType; }
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,23 @@
|
|||||||
package com.example.petstoremobile.fragments;
|
package com.example.petstoremobile.fragments;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.provider.OpenableColumns;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.view.GravityCompat;
|
import androidx.core.view.GravityCompat;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ChatAdapter;
|
import com.example.petstoremobile.adapters.ChatAdapter;
|
||||||
import com.example.petstoremobile.adapters.MessageAdapter;
|
import com.example.petstoremobile.adapters.MessageAdapter;
|
||||||
@@ -41,8 +49,15 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
private RecyclerView rvChatList, rvMessages;
|
private RecyclerView rvChatList, rvMessages;
|
||||||
private EditText etMessage;
|
private EditText etMessage;
|
||||||
private Button btnSend;
|
private Button btnSend;
|
||||||
|
private ImageButton btnAttach;
|
||||||
private TextView tvChatTitle;
|
private TextView tvChatTitle;
|
||||||
|
|
||||||
|
// Preview views
|
||||||
|
private View layoutAttachmentPreview;
|
||||||
|
private ImageView ivPreview;
|
||||||
|
private TextView tvPreviewName;
|
||||||
|
private ImageButton btnRemoveAttachment;
|
||||||
|
|
||||||
// Adapters
|
// Adapters
|
||||||
private ChatAdapter chatAdapter;
|
private ChatAdapter chatAdapter;
|
||||||
private MessageAdapter messageAdapter;
|
private MessageAdapter messageAdapter;
|
||||||
@@ -51,6 +66,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
private final List<Chat> chatList = new ArrayList<>();
|
private final List<Chat> chatList = new ArrayList<>();
|
||||||
private final List<Message> messageList = new ArrayList<>();
|
private final List<Message> messageList = new ArrayList<>();
|
||||||
private final Map<Long, String> customerNames = new HashMap<>();
|
private final Map<Long, String> customerNames = new HashMap<>();
|
||||||
|
private Uri pendingAttachmentUri;
|
||||||
|
|
||||||
// APIs
|
// APIs
|
||||||
private ChatApi chatApi;
|
private ChatApi chatApi;
|
||||||
@@ -61,6 +77,24 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
private Long currentUserId;
|
private Long currentUserId;
|
||||||
private Long activeConversationId;
|
private Long activeConversationId;
|
||||||
private StompChatManager stompChatManager;
|
private StompChatManager stompChatManager;
|
||||||
|
private ActivityResultLauncher<Intent> attachmentLauncher;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
attachmentLauncher = registerForActivityResult(
|
||||||
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
|
result -> {
|
||||||
|
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
|
||||||
|
Uri uri = result.getData().getData();
|
||||||
|
if (uri != null) {
|
||||||
|
showAttachmentPreview(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
@@ -77,11 +111,28 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
rvMessages = view.findViewById(R.id.rvMessages);
|
rvMessages = view.findViewById(R.id.rvMessages);
|
||||||
etMessage = view.findViewById(R.id.etMessage);
|
etMessage = view.findViewById(R.id.etMessage);
|
||||||
btnSend = view.findViewById(R.id.btnSend);
|
btnSend = view.findViewById(R.id.btnSend);
|
||||||
|
btnAttach = view.findViewById(R.id.btnAttach);
|
||||||
tvChatTitle = view.findViewById(R.id.tvChatTitle);
|
tvChatTitle = view.findViewById(R.id.tvChatTitle);
|
||||||
|
|
||||||
|
layoutAttachmentPreview = view.findViewById(R.id.layoutAttachmentPreview);
|
||||||
|
ivPreview = view.findViewById(R.id.ivPreview);
|
||||||
|
tvPreviewName = view.findViewById(R.id.tvPreviewName);
|
||||||
|
btnRemoveAttachment = view.findViewById(R.id.btnRemoveAttachment);
|
||||||
|
|
||||||
ImageButton hamburger = view.findViewById(R.id.btnHamburger);
|
ImageButton hamburger = view.findViewById(R.id.btnHamburger);
|
||||||
hamburger.setOnClickListener(v -> drawerLayout.openDrawer(GravityCompat.START));
|
hamburger.setOnClickListener(v -> drawerLayout.openDrawer(GravityCompat.START));
|
||||||
btnSend.setOnClickListener(v -> sendMessage());
|
//When the send button is clicked check if there is an attachment and send using the correct helper function
|
||||||
|
btnSend.setOnClickListener(v -> {
|
||||||
|
if (pendingAttachmentUri != null) {
|
||||||
|
sendWithAttachment(pendingAttachmentUri);
|
||||||
|
} else {
|
||||||
|
sendMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//When the attachment button is clicked open the file picker
|
||||||
|
btnAttach.setOnClickListener(v -> selectAttachment());
|
||||||
|
btnRemoveAttachment.setOnClickListener(v -> removeAttachment());
|
||||||
|
|
||||||
setupRecyclerViews();
|
setupRecyclerViews();
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
@@ -89,6 +140,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to setup recycler views for chat and messages
|
||||||
private void setupRecyclerViews() {
|
private void setupRecyclerViews() {
|
||||||
// Set up Drawer menu to select conversation
|
// Set up Drawer menu to select conversation
|
||||||
chatAdapter = new ChatAdapter(chatList, this);
|
chatAdapter = new ChatAdapter(chatList, this);
|
||||||
@@ -273,6 +325,68 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Helper function to open file picker when the attachment button is clicked
|
||||||
|
private void selectAttachment() {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
intent.setType("*/*");
|
||||||
|
attachmentLauncher.launch(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper function to show the attachment preview
|
||||||
|
private void showAttachmentPreview(Uri uri) {
|
||||||
|
pendingAttachmentUri = uri;
|
||||||
|
layoutAttachmentPreview.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
String mimeType = requireContext().getContentResolver().getType(uri);
|
||||||
|
String fileName = getFileName(uri);
|
||||||
|
tvPreviewName.setText(fileName);
|
||||||
|
|
||||||
|
// If the file is an image, display a thumbnail of the image as well
|
||||||
|
if (mimeType != null && mimeType.startsWith("image/")) {
|
||||||
|
ivPreview.setVisibility(View.VISIBLE);
|
||||||
|
Glide.with(this).load(uri).into(ivPreview);
|
||||||
|
} else {
|
||||||
|
ivPreview.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper function to remove the attachment
|
||||||
|
private void removeAttachment() {
|
||||||
|
pendingAttachmentUri = null;
|
||||||
|
layoutAttachmentPreview.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper function to get the file name from the uri to display in attachment preview
|
||||||
|
private String getFileName(Uri uri) {
|
||||||
|
String result = null;
|
||||||
|
if (uri.getScheme().equals("content")) {
|
||||||
|
try (Cursor cursor = requireContext().getContentResolver().query(uri, null, null, null, null)) {
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
int index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
||||||
|
if (index != -1) {
|
||||||
|
result = cursor.getString(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == null) {
|
||||||
|
result = uri.getPath();
|
||||||
|
int cut = result.lastIndexOf('/');
|
||||||
|
if (cut != -1) {
|
||||||
|
result = result.substring(cut + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper function to send the message with attachment
|
||||||
|
private void sendWithAttachment(Uri uri) {
|
||||||
|
if (activeConversationId == null) return;
|
||||||
|
|
||||||
|
//TODO: send the message with attachment when backend is done
|
||||||
|
Log.d(TAG, "Send with attachment happening");
|
||||||
|
}
|
||||||
|
|
||||||
// When a message is received updates the chat preview
|
// When a message is received updates the chat preview
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(MessageDTO dto) {
|
public void onMessageReceived(MessageDTO dto) {
|
||||||
@@ -370,6 +484,9 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
m.setContent(dto.getContent());
|
m.setContent(dto.getContent());
|
||||||
m.setTimestamp(dto.getTimestamp());
|
m.setTimestamp(dto.getTimestamp());
|
||||||
m.setIsRead(dto.getIsRead());
|
m.setIsRead(dto.getIsRead());
|
||||||
|
m.setAttachmentUrl(dto.getAttachmentUrl());
|
||||||
|
m.setAttachmentName(dto.getAttachmentName());
|
||||||
|
m.setAttachmentType(dto.getAttachmentType());
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,9 +524,11 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
private void setConversationActive(boolean active) {
|
private void setConversationActive(boolean active) {
|
||||||
btnSend.setEnabled(active);
|
btnSend.setEnabled(active);
|
||||||
etMessage.setEnabled(active);
|
etMessage.setEnabled(active);
|
||||||
|
btnAttach.setEnabled(active);
|
||||||
if (!active) {
|
if (!active) {
|
||||||
activeConversationId = null;
|
activeConversationId = null;
|
||||||
ChatNotificationService.activeConversationIdInUi = null;
|
ChatNotificationService.activeConversationIdInUi = null;
|
||||||
|
removeAttachment();
|
||||||
if (tvChatTitle != null) tvChatTitle.setText("Customer Chat");
|
if (tvChatTitle != null) tvChatTitle.setText("Customer Chat");
|
||||||
if (stompChatManager != null) {
|
if (stompChatManager != null) {
|
||||||
stompChatManager.clearConversationSubscription();
|
stompChatManager.clearConversationSubscription();
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ public class Message {
|
|||||||
private String content;
|
private String content;
|
||||||
private String timestamp;
|
private String timestamp;
|
||||||
private Boolean isRead;
|
private Boolean isRead;
|
||||||
|
private String attachmentUrl;
|
||||||
|
private String attachmentName;
|
||||||
|
private String attachmentType;
|
||||||
|
|
||||||
public Message() {}
|
public Message() {}
|
||||||
|
|
||||||
@@ -33,4 +36,13 @@ public class Message {
|
|||||||
|
|
||||||
public Boolean getIsRead() { return isRead; }
|
public Boolean getIsRead() { return isRead; }
|
||||||
public void setIsRead(Boolean isRead) { this.isRead = isRead; }
|
public void setIsRead(Boolean isRead) { this.isRead = isRead; }
|
||||||
|
|
||||||
|
public String getAttachmentUrl() { return attachmentUrl; }
|
||||||
|
public void setAttachmentUrl(String attachmentUrl) { this.attachmentUrl = attachmentUrl; }
|
||||||
|
|
||||||
|
public String getAttachmentName() { return attachmentName; }
|
||||||
|
public void setAttachmentName(String attachmentName) { this.attachmentName = attachmentName; }
|
||||||
|
|
||||||
|
public String getAttachmentType() { return attachmentType; }
|
||||||
|
public void setAttachmentType(String attachmentType) { this.attachmentType = attachmentType; }
|
||||||
}
|
}
|
||||||
@@ -49,12 +49,59 @@
|
|||||||
android:clipToPadding="false" />
|
android:clipToPadding="false" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutAttachmentPreview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
|
android:background="#E0E0E0"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivPreview"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPreviewName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="@color/text_dark"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnRemoveAttachment"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:src="@android:drawable/ic_menu_close_clear_cancel"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Remove attachment"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:background="@color/white">
|
android:background="@color/white">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnAttach"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:src="@android:drawable/ic_menu_add"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Attach file"
|
||||||
|
android:layout_marginEnd="4dp"/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/etMessage"
|
android:id="@+id/etMessage"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|||||||
@@ -6,14 +6,38 @@
|
|||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
android:gravity="start">
|
android:gravity="start">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/tvMessageContent"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
android:background="@drawable/bg_message_received"
|
android:background="@drawable/bg_message_received"
|
||||||
android:padding="12dp"
|
android:padding="8dp"
|
||||||
android:text="Received message"
|
android:maxWidth="300dp">
|
||||||
android:textColor="@color/text_dark"
|
|
||||||
android:maxWidth="300dp" />
|
<ImageView
|
||||||
|
android:id="@+id/ivAttachment"
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvAttachmentName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvMessageContent"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Received message"
|
||||||
|
android:textColor="@color/text_dark" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -6,14 +6,38 @@
|
|||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
android:gravity="end">
|
android:gravity="end">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/tvMessageContent"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
android:background="@drawable/bg_message_sent"
|
android:background="@drawable/bg_message_sent"
|
||||||
android:padding="12dp"
|
android:padding="8dp"
|
||||||
android:text="Sent message"
|
android:maxWidth="300dp">
|
||||||
android:textColor="@color/white"
|
|
||||||
android:maxWidth="300dp" />
|
<ImageView
|
||||||
|
android:id="@+id/ivAttachment"
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvAttachmentName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvMessageContent"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Sent message"
|
||||||
|
android:textColor="@color/white" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user