From 177ac844ee2cad24a7ec9e803e5441e1449e094f Mon Sep 17 00:00:00 2001 From: Alex <78383757+Lextical@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:13:27 -0600 Subject: [PATCH 1/2] Added push notifications when reciving any message and added filter status on pets in Andriod --- .../activities/HomeActivity.java | 8 +- .../fragments/ChatFragment.java | 13 +- .../fragments/listfragments/PetFragment.java | 55 ++++++-- .../services/ChatNotificationService.java | 119 +++++++++++++----- .../utils/NotificationHelper.java | 5 +- .../app/src/main/res/layout/fragment_pet.xml | 36 ++++-- 6 files changed, 181 insertions(+), 55 deletions(-) diff --git a/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java b/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java index 9a286f00..bc646e26 100644 --- a/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java +++ b/android/app/src/main/java/com/example/petstoremobile/activities/HomeActivity.java @@ -88,7 +88,13 @@ public class HomeActivity extends AppCompatActivity { // like clicking a notification or just launching the app from a fresh start private void handleIntent(Intent intent) { if (intent != null && "chat".equals(intent.getStringExtra("navigate_to"))) { - loadFragment(new ChatFragment()); + ChatFragment chatFragment = new ChatFragment(); + if (intent.hasExtra("conversation_id")) { + Bundle args = new Bundle(); + args.putLong("conversation_id", intent.getLongExtra("conversation_id", -1)); + chatFragment.setArguments(args); + } + loadFragment(chatFragment); bottomNav.setSelectedItemId(R.id.nav_chat); } else { loadFragment(new ListFragment()); diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java index b73fdc6b..08d9e2f4 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java @@ -121,6 +121,10 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis Log.e(TAG, "No token found"); } + if (getArguments() != null && getArguments().containsKey("conversation_id")) { + activeConversationId = getArguments().getLong("conversation_id"); + } + loadCustomers(); } @@ -165,7 +169,14 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis .collect(Collectors.toList()); chatList.addAll(loaded); chatAdapter.notifyDataSetChanged(); - if (activeConversationId == null) { + + if (activeConversationId != null) { + setConversationActive(true); + if (stompChatManager != null) { + stompChatManager.subscribeToConversation(activeConversationId); + } + loadMessageHistory(activeConversationId); + } else { messageList.clear(); messageAdapter.notifyDataSetChanged(); setConversationActive(false); diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java index 6448b5f3..91257673 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java @@ -13,8 +13,11 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageButton; +import android.widget.Spinner; import android.widget.Toast; import com.example.petstoremobile.R; @@ -43,6 +46,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen private PetApi api; private SwipeRefreshLayout swipeRefreshLayout; private EditText etSearch; + private Spinner spinnerStatus; //load pet view @Override @@ -57,6 +61,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen setupRecyclerView(view); setupSearch(view); + setupStatusFilter(view); setupSwipeRefresh(view); loadPetData(); @@ -82,24 +87,48 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen etSearch.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - filterPets(s.toString()); + filterPets(); } @Override public void afterTextChanged(Editable s) {} }); } - private void filterPets(String query) { + //Setup the status filter spinner + private void setupStatusFilter(View view) { + spinnerStatus = view.findViewById(R.id.spinnerStatus); + String[] statuses = {"All Statuses", "Available", "Adopted"}; + ArrayAdapter adapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, statuses); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinnerStatus.setAdapter(adapter); + + spinnerStatus.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + filterPets(); + } + + @Override + public void onNothingSelected(AdapterView parent) {} + }); + } + + // Helper function to filter pets based on search and status filter + private void filterPets() { + String query = etSearch.getText().toString().toLowerCase(); + String selectedStatus = spinnerStatus.getSelectedItem().toString(); + filteredList.clear(); - if (query.isEmpty()) { - filteredList.addAll(petList); - } else { - String lower = query.toLowerCase(); - for (PetDTO p : petList) { - if (p.getPetName().toLowerCase().contains(lower) - || p.getPetSpecies().toLowerCase().contains(lower) - || p.getPetBreed().toLowerCase().contains(lower)) { - filteredList.add(p); - } + for (PetDTO p : petList) { + boolean matchesSearch = query.isEmpty() || + p.getPetName().toLowerCase().contains(query) || + p.getPetSpecies().toLowerCase().contains(query) || + p.getPetBreed().toLowerCase().contains(query); + + boolean matchesStatus = selectedStatus.equals("All Statuses") || + p.getPetStatus().equalsIgnoreCase(selectedStatus); + + if (matchesSearch && matchesStatus) { + filteredList.add(p); } } adapter.notifyDataSetChanged(); @@ -173,7 +202,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen if (response.isSuccessful() && response.body() != null) { petList.clear(); petList.addAll(response.body().getContent()); - filterPets(etSearch.getText().toString()); + filterPets(); } else { Log.e("onResponse: ", response.message()); diff --git a/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java b/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java index fadd1886..5d1ef582 100644 --- a/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java +++ b/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java @@ -5,18 +5,26 @@ import android.content.Intent; import android.os.IBinder; import android.util.Log; import androidx.annotation.Nullable; +import com.example.petstoremobile.api.ChatApi; +import com.example.petstoremobile.api.RetrofitClient; import com.example.petstoremobile.api.auth.TokenManager; import com.example.petstoremobile.dtos.ConversationDTO; +import com.example.petstoremobile.dtos.MessageDTO; import com.example.petstoremobile.utils.NotificationHelper; import com.example.petstoremobile.websocket.StompChatManager; import java.util.HashSet; +import java.util.List; import java.util.Set; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; // Service to receive notifications when a new conversation is created public class ChatNotificationService extends Service { private static final String TAG = "ChatNotificationService"; private StompChatManager stompChatManager; private final Set knownConversationIds = new HashSet<>(); + private Long currentUserId; //When the service starts, connect to the websocket @Override @@ -32,45 +40,98 @@ public class ChatNotificationService extends Service { TokenManager tm = TokenManager.getInstance(this); String token = tm.getToken(); String role = tm.getRole(); - + currentUserId = tm.getUserId(); if (token != null && stompChatManager == null) { - stompChatManager = new StompChatManager(token, role); - - //When a conversation gets created, show a notification - stompChatManager.setConversationListener(conversation -> { - //check if the conversation exists - if (conversation != null && conversation.getId() != null) { - //check if the conversation is new - if (!knownConversationIds.contains(conversation.getId())) { - //add the conversation to the set of known conversations - knownConversationIds.add(conversation.getId()); - NotificationHelper.showNotification( - getApplicationContext(), - "Customer Support", - "A customer request for assistance" - ); - + // Fetch existing conversations + ChatApi chatApi = RetrofitClient.getChatApi(this); + chatApi.getAllConversations().enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (response.isSuccessful() && response.body() != null) { + for (ConversationDTO conversation : response.body()) { + if (conversation.getId() != null) { + knownConversationIds.add(conversation.getId()); + // subscribe to existing conversations to get message notifications + if (stompChatManager != null) { + stompChatManager.subscribeToConversation(conversation.getId()); + } + } + } + Log.d(TAG, "Loaded " + knownConversationIds.size() + " existing conversations"); } - } - }); - stompChatManager.setConnectionListener(new StompChatManager.ConnectionListener() { - // when the websocket is connected, set isFirstLoad to false after a delay - @Override - public void onSocketOpened() { - Log.d(TAG, "WebSocket connected in service"); + startStomp(token, role); } @Override - public void onSocketClosed() { Log.d(TAG, "WebSocket closed in service"); } - - @Override - public void onSocketError() { Log.e(TAG, "WebSocket error in service"); } + public void onFailure(Call> call, Throwable t) { + Log.e(TAG, "Failed to load existing conversations", t); + //tries to connect if loading fails + startStomp(token, role); + } }); - stompChatManager.connect(); } } + private void startStomp(String token, String role) { + if (stompChatManager != null) return; + + stompChatManager = new StompChatManager(token, role); + + // Listen for messages in existing conversations + stompChatManager.setMessageListener(message -> { + if (message != null && !message.getSenderId().equals(currentUserId)) { + NotificationHelper.showNotification( + getApplicationContext(), + "New Message", + message.getContent(), + message.getConversationId() + ); + } + }); + + //When a conversation gets created, show a notification + stompChatManager.setConversationListener(conversation -> { + //check if the conversation exists + if (conversation != null && conversation.getId() != null) { + //check if the conversation is new + if (!knownConversationIds.contains(conversation.getId())) { + //add the conversation to the set of known conversations + knownConversationIds.add(conversation.getId()); + + // Subscribe to the new conversation's messages + stompChatManager.subscribeToConversation(conversation.getId()); + + NotificationHelper.showNotification( + getApplicationContext(), + "New Support Request", + "A customer is requesting assistance", + conversation.getId() + ); + } + } + }); + + // Subscribe to existing conversations if they were already loaded + for (Long id : knownConversationIds) { + stompChatManager.subscribeToConversation(id); + } + + stompChatManager.setConnectionListener(new StompChatManager.ConnectionListener() { + @Override + public void onSocketOpened() { + Log.d(TAG, "WebSocket connected in service"); + } + + @Override + public void onSocketClosed() { Log.d(TAG, "WebSocket closed in service"); } + + @Override + public void onSocketError() { Log.e(TAG, "WebSocket error in service"); } + }); + stompChatManager.connect(); + } + //When the service is destroyed, disconnect from the websocket @Override public void onDestroy() { diff --git a/android/app/src/main/java/com/example/petstoremobile/utils/NotificationHelper.java b/android/app/src/main/java/com/example/petstoremobile/utils/NotificationHelper.java index 7ec80cb7..cf89b42b 100644 --- a/android/app/src/main/java/com/example/petstoremobile/utils/NotificationHelper.java +++ b/android/app/src/main/java/com/example/petstoremobile/utils/NotificationHelper.java @@ -18,7 +18,7 @@ public class NotificationHelper { private static final int NOTIFICATION_ID = 1; // a function to show a notification - public static void showNotification(Context context, String title, String message) { + public static void showNotification(Context context, String title, String message, Long conversationId) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); //check if the device is running on Oreo or higher so we can set up a notification channel @@ -34,6 +34,9 @@ public class NotificationHelper { Intent intent = new Intent(context, HomeActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.putExtra("navigate_to", "chat"); + if (conversationId != null) { + intent.putExtra("conversation_id", conversationId); + } PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); diff --git a/android/app/src/main/res/layout/fragment_pet.xml b/android/app/src/main/res/layout/fragment_pet.xml index 2ad2d22d..1f625bac 100644 --- a/android/app/src/main/res/layout/fragment_pet.xml +++ b/android/app/src/main/res/layout/fragment_pet.xml @@ -38,18 +38,34 @@ - + android:orientation="horizontal" + android:padding="8dp" + android:gravity="center_vertical"> + + + + + Date: Thu, 26 Mar 2026 21:31:36 -0600 Subject: [PATCH 2/2] Make chat notification display messengers name and disable notifying if already in chat view --- .../fragments/ChatFragment.java | 16 +++ .../services/ChatNotificationService.java | 119 ++++++++++++++---- .../app/src/main/res/layout/fragment_chat.xml | 5 +- 3 files changed, 118 insertions(+), 22 deletions(-) diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java index 08d9e2f4..0e405c63 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java @@ -25,6 +25,7 @@ import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.SendMessageRequest; import com.example.petstoremobile.models.Chat; import com.example.petstoremobile.models.Message; +import com.example.petstoremobile.services.ChatNotificationService; import com.example.petstoremobile.websocket.StompChatManager; import java.util.*; import java.util.stream.Collectors; @@ -40,6 +41,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis private RecyclerView rvChatList, rvMessages; private EditText etMessage; private Button btnSend; + private TextView tvChatTitle; // Adapters private ChatAdapter chatAdapter; @@ -75,6 +77,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis rvMessages = view.findViewById(R.id.rvMessages); etMessage = view.findViewById(R.id.etMessage); btnSend = view.findViewById(R.id.btnSend); + tvChatTitle = view.findViewById(R.id.tvChatTitle); ImageButton hamburger = view.findViewById(R.id.btnHamburger); hamburger.setOnClickListener(v -> drawerLayout.openDrawer(GravityCompat.START)); @@ -172,6 +175,13 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis if (activeConversationId != null) { setConversationActive(true); + // Update title to customer name of active conversation + for (Chat chat : chatList) { + if (chat.getChatId().equals(String.valueOf(activeConversationId))) { + tvChatTitle.setText(chat.getCustomerName()); + break; + } + } if (stompChatManager != null) { stompChatManager.subscribeToConversation(activeConversationId); } @@ -197,6 +207,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis public void onChatClick(Chat chat) { activeConversationId = Long.parseLong(chat.getChatId()); setConversationActive(true); + tvChatTitle.setText(chat.getCustomerName()); drawerLayout.closeDrawer(GravityCompat.START); if (stompChatManager != null) { @@ -316,6 +327,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis if (activeConversationId != null && activeConversationId.equals(dto.getId())) { setConversationActive(true); + tvChatTitle.setText(name); } } @@ -397,6 +409,8 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis etMessage.setEnabled(active); if (!active) { activeConversationId = null; + ChatNotificationService.activeConversationIdInUi = null; + if (tvChatTitle != null) tvChatTitle.setText("Customer Chat"); if (stompChatManager != null) { stompChatManager.clearConversationSubscription(); } @@ -406,6 +420,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis etMessage.setHint("Select a chat to start messaging"); } else { etMessage.setHint("Type a message..."); + ChatNotificationService.activeConversationIdInUi = activeConversationId; } } @@ -413,6 +428,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis @Override public void onDestroyView() { super.onDestroyView(); + ChatNotificationService.activeConversationIdInUi = null; if (stompChatManager != null) stompChatManager.disconnect(); } } diff --git a/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java b/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java index 5d1ef582..a1e16fa6 100644 --- a/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java +++ b/android/app/src/main/java/com/example/petstoremobile/services/ChatNotificationService.java @@ -4,16 +4,22 @@ import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.example.petstoremobile.api.ChatApi; +import com.example.petstoremobile.api.CustomerApi; import com.example.petstoremobile.api.RetrofitClient; import com.example.petstoremobile.api.auth.TokenManager; import com.example.petstoremobile.dtos.ConversationDTO; +import com.example.petstoremobile.dtos.CustomerDTO; import com.example.petstoremobile.dtos.MessageDTO; +import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.utils.NotificationHelper; import com.example.petstoremobile.websocket.StompChatManager; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import retrofit2.Call; import retrofit2.Callback; @@ -22,8 +28,13 @@ import retrofit2.Response; // Service to receive notifications when a new conversation is created public class ChatNotificationService extends Service { private static final String TAG = "ChatNotificationService"; + + public static Long activeConversationIdInUi = null; + private StompChatManager stompChatManager; private final Set knownConversationIds = new HashSet<>(); + private final Map conversationToCustomerId = new HashMap<>(); + private final Map customerIdToName = new HashMap<>(); private Long currentUserId; //When the service starts, connect to the websocket @@ -43,36 +54,59 @@ public class ChatNotificationService extends Service { currentUserId = tm.getUserId(); if (token != null && stompChatManager == null) { - // Fetch existing conversations - ChatApi chatApi = RetrofitClient.getChatApi(this); - chatApi.getAllConversations().enqueue(new Callback>() { + //load customers to have names associated with customer ids + CustomerApi customerApi = RetrofitClient.getCustomerApi(this); + customerApi.getAllCustomers(0, 1000).enqueue(new Callback>() { @Override - public void onResponse(Call> call, Response> response) { + public void onResponse(@NonNull Call> call, @NonNull Response> response) { if (response.isSuccessful() && response.body() != null) { - for (ConversationDTO conversation : response.body()) { - if (conversation.getId() != null) { - knownConversationIds.add(conversation.getId()); - // subscribe to existing conversations to get message notifications - if (stompChatManager != null) { - stompChatManager.subscribeToConversation(conversation.getId()); - } - } + for (CustomerDTO customer : response.body().getContent()) { + customerIdToName.put(customer.getCustomerId(), customer.getFullName()); } - Log.d(TAG, "Loaded " + knownConversationIds.size() + " existing conversations"); } - startStomp(token, role); + loadConversationsAndStartStomp(token, role); } @Override - public void onFailure(Call> call, Throwable t) { - Log.e(TAG, "Failed to load existing conversations", t); - //tries to connect if loading fails - startStomp(token, role); + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + Log.e(TAG, "Failed to load customers", t); + loadConversationsAndStartStomp(token, role); } }); } } + private void loadConversationsAndStartStomp(String token, String role) { + // Fetch existing conversations + ChatApi chatApi = RetrofitClient.getChatApi(this); + chatApi.getAllConversations().enqueue(new Callback>() { + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + if (response.isSuccessful() && response.body() != null) { + for (ConversationDTO conversation : response.body()) { + if (conversation.getId() != null) { + knownConversationIds.add(conversation.getId()); + conversationToCustomerId.put(conversation.getId(), conversation.getCustomerId()); + // subscribe to existing conversations to get message notifications + if (stompChatManager != null) { + stompChatManager.subscribeToConversation(conversation.getId()); + } + } + } + Log.d(TAG, "Loaded " + knownConversationIds.size() + " existing conversations"); + } + startStomp(token, role); + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + Log.e(TAG, "Failed to load existing conversations", t); + //tries to connect if loading fails + startStomp(token, role); + } + }); + } + private void startStomp(String token, String role) { if (stompChatManager != null) return; @@ -81,9 +115,23 @@ public class ChatNotificationService extends Service { // Listen for messages in existing conversations stompChatManager.setMessageListener(message -> { if (message != null && !message.getSenderId().equals(currentUserId)) { + // Check if this conversation is already active in the view + //if it is then don't make a notification for this chat + if (activeConversationIdInUi != null && activeConversationIdInUi.equals(message.getConversationId())) { + Log.d(TAG, "Disable notification for active conversation: " + message.getConversationId()); + return; + } + + String title = "New Message"; + Long customerId = conversationToCustomerId.get(message.getConversationId()); + if (customerId != null && customerIdToName.containsKey(customerId)) { + //append the customer name to the title of the notification + title = "New message from " + customerIdToName.get(customerId); + } + NotificationHelper.showNotification( getApplicationContext(), - "New Message", + title, message.getContent(), message.getConversationId() ); @@ -98,13 +146,24 @@ public class ChatNotificationService extends Service { if (!knownConversationIds.contains(conversation.getId())) { //add the conversation to the set of known conversations knownConversationIds.add(conversation.getId()); - + conversationToCustomerId.put(conversation.getId(), conversation.getCustomerId()); + // Subscribe to the new conversation's messages stompChatManager.subscribeToConversation(conversation.getId()); + + String title = "New Support Request"; + if (customerIdToName.containsKey(conversation.getCustomerId())) { + //append the customer name to the title of the notification + title = "New Support Request from " + customerIdToName.get(conversation.getCustomerId()); + } else { + // Try to fetch customer name for the new request + fetchCustomerName(conversation.getCustomerId()); + } + //Display a notification NotificationHelper.showNotification( getApplicationContext(), - "New Support Request", + title, "A customer is requesting assistance", conversation.getId() ); @@ -132,6 +191,24 @@ public class ChatNotificationService extends Service { stompChatManager.connect(); } + // Helper function to fetch customer name for a conversation + private void fetchCustomerName(Long customerId) { + CustomerApi customerApi = RetrofitClient.getCustomerApi(this); + customerApi.getCustomerById(customerId).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful() && response.body() != null) { + customerIdToName.put(customerId, response.body().getFullName()); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + Log.e(TAG, "Failed to fetch customer name", t); + } + }); + } + //When the service is destroyed, disconnect from the websocket @Override public void onDestroy() { diff --git a/android/app/src/main/res/layout/fragment_chat.xml b/android/app/src/main/res/layout/fragment_chat.xml index e56e283f..875bccfd 100644 --- a/android/app/src/main/res/layout/fragment_chat.xml +++ b/android/app/src/main/res/layout/fragment_chat.xml @@ -28,12 +28,15 @@ android:contentDescription="Open menu"/> + android:textStyle="bold" + android:paddingStart="8dp" + android:paddingEnd="8dp"/>