Skip to content

Commit 37d1972

Browse files
committed
Implement dedicated UI for deleted messages, including distinct sent and received message bubbles and improved contact resolution.
1 parent 4f9f568 commit 37d1972

23 files changed

Lines changed: 1054 additions & 213 deletions

app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
1212
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
1313
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
14+
<uses-permission android:name="android.permission.READ_CONTACTS" />
1415

1516
<uses-permission
1617
android:name="android.permission.READ_EXTERNAL_STORAGE"
@@ -57,6 +58,11 @@
5758
</service>
5859

5960

61+
<provider
62+
android:name=".provider.DeletedMessagesProvider"
63+
android:authorities="com.wmods.wppenhacer.provider"
64+
android:exported="true" />
65+
6066
<activity
6167
android:name=".activities.MainActivity"
6268
android:exported="true"

app/src/main/java/com/wmods/wppenhacer/activities/DeletedMessagesActivity.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,29 @@ protected void onCreate(Bundle savedInstanceState) {
2424
}
2525

2626
if (savedInstanceState == null) {
27-
getSupportFragmentManager().beginTransaction()
28-
.replace(R.id.fragment_container, new DeletedMessagesFragment())
29-
.commit();
27+
setupViewPager();
3028
}
3129
}
3230

31+
private void setupViewPager() {
32+
binding.viewPager.setAdapter(new androidx.viewpager2.adapter.FragmentStateAdapter(this) {
33+
@androidx.annotation.NonNull
34+
@Override
35+
public androidx.fragment.app.Fragment createFragment(int position) {
36+
return DeletedMessagesFragment.newInstance(position == 1); // 0 = Individual, 1 = Group
37+
}
38+
39+
@Override
40+
public int getItemCount() {
41+
return 2;
42+
}
43+
});
44+
45+
new com.google.android.material.tabs.TabLayoutMediator(binding.tabLayout, binding.viewPager, (tab, position) -> {
46+
tab.setText(position == 0 ? "Individuals" : "Groups");
47+
}).attach();
48+
}
49+
3350
@Override
3451
public boolean onOptionsItemSelected(MenuItem item) {
3552
if (item.getItemId() == android.R.id.home) {

app/src/main/java/com/wmods/wppenhacer/activities/MessageListActivity.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ protected void onCreate(Bundle savedInstanceState) {
3939
setSupportActionBar(binding.toolbar);
4040
if (getSupportActionBar() != null) {
4141
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
42-
String title = WppCore.stripJID(chatJid);
42+
String title = chatJid;
43+
if (title != null) {
44+
title = title.replace("@s.whatsapp.net", "").replace("@g.us", "");
45+
if (title.contains("@")) title = title.split("@")[0];
46+
}
4347
getSupportActionBar().setTitle(title);
4448
}
4549

@@ -79,6 +83,6 @@ public boolean onOptionsItemSelected(MenuItem item) {
7983

8084
@Override
8185
public void onRestoreClick(DeletedMessage message) {
82-
com.wmods.wppenhacer.xposed.features.general.RecoverDeleteForMe.restoreMessage(this, message);
86+
Toast.makeText(this, "Restore feature coming soon!", Toast.LENGTH_SHORT).show();
8387
}
8488
}

app/src/main/java/com/wmods/wppenhacer/adapter/DeletedMessagesAdapter.java

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.view.ViewGroup;
66
import android.widget.ImageView;
77
import android.widget.TextView;
8+
import android.content.Context;
89

910
import androidx.annotation.NonNull;
1011
import androidx.recyclerview.widget.RecyclerView;
@@ -24,6 +25,7 @@ public class DeletedMessagesAdapter extends RecyclerView.Adapter<DeletedMessages
2425

2526
public interface OnItemClickListener {
2627
void onItemClick(DeletedMessage message);
28+
void onRestoreClick(DeletedMessage message);
2729
}
2830

2931
public DeletedMessagesAdapter(OnItemClickListener listener) {
@@ -38,7 +40,7 @@ public void setMessages(List<DeletedMessage> messages) {
3840
@NonNull
3941
@Override
4042
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
41-
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_deleted_message_contact, parent, false);
43+
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_contact_row, parent, false);
4244
return new ViewHolder(view);
4345
}
4446

@@ -47,26 +49,57 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
4749
DeletedMessage message = messages.get(position);
4850

4951
// Contact Name
50-
String contactName = WppCore.getContactName(new com.wmods.wppenhacer.xposed.core.components.FMessageWpp.UserJid(message.getChatJid()));
51-
holder.contactName.setText(contactName != null ? contactName : message.getChatJid());
52+
Context context = holder.itemView.getContext();
53+
String displayJid = message.getChatJid();
54+
55+
// Priority 1: Use Persisted Contact Name (from DB)
56+
String contactName = message.getContactName();
57+
58+
// Priority 2: Runtime Lookup (if not in DB or changed)
59+
if (contactName == null && displayJid != null) {
60+
contactName = com.wmods.wppenhacer.utils.ContactHelper.getContactName(context, displayJid);
61+
}
62+
63+
String displayText;
64+
if (contactName != null) {
65+
displayText = contactName;
66+
} else {
67+
// Fallback to formatted JID
68+
displayText = displayJid;
69+
if (displayText != null) {
70+
displayText = displayText.replace("@s.whatsapp.net", "").replace("@g.us", "");
71+
if (displayText.contains("@")) displayText = displayText.split("@")[0];
72+
} else {
73+
displayText = "Unknown";
74+
}
75+
}
76+
77+
holder.contactName.setText(displayText);
5278

5379
// Timestamp
5480
holder.timestamp.setText(Utils.getDateTimeFromMillis(message.getTimestamp()));
5581

56-
// Last Message Content
57-
String content = message.getTextContent();
58-
if (content == null || content.isEmpty()) {
82+
// Message Preview
83+
String text = message.getTextContent();
84+
String senderPrefix = "";
85+
if (message.isFromMe()) {
86+
senderPrefix = "You: ";
87+
}
88+
89+
if (text == null || text.isEmpty()) {
5990
if (message.getMediaType() != -1) {
60-
content = "Media (" + message.getMediaType() + ")";
61-
if (message.getMediaCaption() != null && !message.getMediaCaption().isEmpty()) {
62-
content += ": " + message.getMediaCaption();
63-
}
91+
text = "📷 Photo";
92+
if (message.getMediaType() == 2) text = "🔊 Audio";
93+
if (message.getMediaType() == 3) text = "🎥 Video";
6494
} else {
65-
content = "Deleted Message";
95+
text = "Message deleted";
6696
}
6797
}
68-
holder.lastMessage.setText(content);
98+
holder.lastMessage.setText(senderPrefix + text);
6999

100+
// Avatar (Placeholder)
101+
// Holder.avatar.setImageDrawable(...)
102+
70103
holder.itemView.setOnClickListener(v -> listener.onItemClick(message));
71104
}
72105

@@ -76,17 +109,17 @@ public int getItemCount() {
76109
}
77110

78111
static class ViewHolder extends RecyclerView.ViewHolder {
112+
ImageView avatar;
79113
TextView contactName;
80-
TextView timestamp;
114+
TextView timestamp; // Date
81115
TextView lastMessage;
82-
ImageView icon;
83116

84117
ViewHolder(View itemView) {
85118
super(itemView);
119+
avatar = itemView.findViewById(R.id.avatar);
86120
contactName = itemView.findViewById(R.id.contact_name);
87121
timestamp = itemView.findViewById(R.id.timestamp);
88122
lastMessage = itemView.findViewById(R.id.last_message);
89-
icon = itemView.findViewById(R.id.icon);
90123
}
91124
}
92125
}

app/src/main/java/com/wmods/wppenhacer/adapter/MessageListAdapter.java

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public interface OnRestoreClickListener {
2828
void onRestoreClick(DeletedMessage message);
2929
}
3030

31+
private static final int VIEW_TYPE_SENT = 1;
32+
private static final int VIEW_TYPE_RECEIVED = 2;
33+
3134
public MessageListAdapter(OnRestoreClickListener listener) {
3235
this.listener = listener;
3336
}
@@ -37,46 +40,79 @@ public void setMessages(List<DeletedMessage> messages) {
3740
notifyDataSetChanged();
3841
}
3942

43+
@Override
44+
public int getItemViewType(int position) {
45+
DeletedMessage message = messages.get(position);
46+
return message.isFromMe() ? VIEW_TYPE_SENT : VIEW_TYPE_RECEIVED;
47+
}
48+
4049
@NonNull
4150
@Override
4251
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
43-
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_deleted_message, parent, false);
52+
int layoutId = (viewType == VIEW_TYPE_SENT) ? R.layout.item_message_sent : R.layout.item_message_received;
53+
View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
4454
return new ViewHolder(view);
4555
}
4656

4757
@Override
4858
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
4959
DeletedMessage message = messages.get(position);
5060

51-
holder.senderName.setText(message.getSenderJid());
52-
holder.timestamp.setText(Utils.getDateTimeFromMillis(message.getTimestamp()));
53-
54-
if (message.getTextContent() != null && !message.getTextContent().isEmpty()) {
55-
holder.messageContent.setText(message.getTextContent());
56-
holder.messageContent.setVisibility(View.VISIBLE);
57-
} else {
58-
holder.messageContent.setVisibility(View.GONE);
59-
}
60-
61-
if (message.getMediaPath() != null) {
62-
holder.mediaContainer.setVisibility(View.VISIBLE);
63-
File mediaFile = new File(message.getMediaPath());
64-
if (mediaFile.exists()) {
65-
holder.mediaPreview.setImageURI(Uri.fromFile(mediaFile));
61+
// Sender Name (Only for received messages, and usually specific to groups)
62+
if (holder.senderName != null) {
63+
boolean showName = !message.isFromMe() && message.getChatJid().contains("@g.us");
64+
65+
if (showName) {
66+
String contactName = message.getContactName(); // Try persisted name first
67+
if (contactName == null) {
68+
contactName = com.wmods.wppenhacer.utils.ContactHelper.getContactName(holder.itemView.getContext(), message.getSenderJid());
69+
}
70+
71+
if (contactName != null) {
72+
holder.senderName.setText(contactName);
73+
holder.senderName.setVisibility(View.VISIBLE);
74+
} else {
75+
String senderJid = message.getSenderJid();
76+
if (senderJid != null) {
77+
senderJid = senderJid.replace("@s.whatsapp.net", "").replace("@g.us", "");
78+
if (senderJid.contains("@")) senderJid = senderJid.split("@")[0];
79+
holder.senderName.setText(senderJid);
80+
holder.senderName.setVisibility(View.VISIBLE);
81+
} else {
82+
holder.senderName.setVisibility(View.GONE);
83+
}
84+
}
6685
} else {
67-
holder.mediaPreview.setImageResource(android.R.drawable.ic_menu_report_image);
86+
holder.senderName.setVisibility(View.GONE);
6887
}
88+
}
6989

70-
if (message.getMediaCaption() != null && !message.getMediaCaption().isEmpty()) {
71-
holder.mediaCaption.setText(message.getMediaCaption());
72-
holder.mediaCaption.setVisibility(View.VISIBLE);
73-
} else {
74-
holder.mediaCaption.setVisibility(View.GONE);
75-
}
90+
// Timestamp
91+
holder.timestamp.setText(Utils.getDateTimeFromMillis(message.getTimestamp()));
92+
93+
// Message Content
94+
String text = message.getTextContent();
95+
if (text != null && !text.isEmpty()) {
96+
holder.messageContent.setText(text);
97+
holder.messageContent.setVisibility(View.VISIBLE);
7698
} else {
77-
holder.mediaContainer.setVisibility(View.GONE);
99+
// Placeholder for media
100+
String type = "Message";
101+
if (message.getMediaType() != -1) {
102+
if (message.getMediaType() == 1) type = "📷 Photo";
103+
else if (message.getMediaType() == 2) type = "🔊 Audio";
104+
else if (message.getMediaType() == 3) type = "🎥 Video";
105+
else type = "📁 Media (" + message.getMediaType() + ")";
106+
}
107+
108+
if (message.getMediaCaption() != null && !message.getMediaCaption().isEmpty()) {
109+
type += "\n" + message.getMediaCaption();
110+
}
111+
holder.messageContent.setText(type);
112+
holder.messageContent.setVisibility(View.VISIBLE);
78113
}
79114

115+
// Restore Button
80116
holder.btnRestore.setOnClickListener(v -> listener.onRestoreClick(message));
81117
}
82118

@@ -86,22 +122,16 @@ public int getItemCount() {
86122
}
87123

88124
static class ViewHolder extends RecyclerView.ViewHolder {
89-
TextView senderName;
125+
TextView senderName; // Nullable (only in received)
90126
TextView timestamp;
91127
TextView messageContent;
92-
View mediaContainer;
93-
ImageView mediaPreview;
94-
TextView mediaCaption;
95-
MaterialButton btnRestore;
128+
View btnRestore;
96129

97130
ViewHolder(View itemView) {
98131
super(itemView);
99132
senderName = itemView.findViewById(R.id.sender_name);
100133
timestamp = itemView.findViewById(R.id.timestamp);
101134
messageContent = itemView.findViewById(R.id.message_content);
102-
mediaContainer = itemView.findViewById(R.id.media_container);
103-
mediaPreview = itemView.findViewById(R.id.media_preview);
104-
mediaCaption = itemView.findViewById(R.id.media_caption);
105135
btnRestore = itemView.findViewById(R.id.btn_restore);
106136
}
107137
}

0 commit comments

Comments
 (0)