Improved chat message display
This commit is contained in:
parent
15ab10b4cb
commit
f110e817d5
6 changed files with 119 additions and 118 deletions
|
@ -76,10 +76,10 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
public final ImageView outgoingImdn;
|
public final ImageView outgoingImdn;
|
||||||
public final TextView messageText;
|
public final TextView messageText;
|
||||||
|
|
||||||
public final FlexboxLayout pictures;
|
public final FlexboxLayout multiFileContents;
|
||||||
|
public final RelativeLayout singleFileContent;
|
||||||
|
|
||||||
public final CheckBox deleteEvent;
|
public final CheckBox delete;
|
||||||
public final CheckBox deleteMessage;
|
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ChatMessageViewHolderClickListener mListener;
|
private ChatMessageViewHolderClickListener mListener;
|
||||||
|
@ -111,10 +111,10 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
outgoingImdn = view.findViewById(R.id.imdn);
|
outgoingImdn = view.findViewById(R.id.imdn);
|
||||||
messageText = view.findViewById(R.id.message);
|
messageText = view.findViewById(R.id.message);
|
||||||
|
|
||||||
pictures = view.findViewById(R.id.pictures);
|
singleFileContent = view.findViewById(R.id.single_content);
|
||||||
|
multiFileContents = view.findViewById(R.id.multi_content);
|
||||||
|
|
||||||
deleteEvent = view.findViewById(R.id.delete_event);
|
delete = view.findViewById(R.id.delete_event);
|
||||||
deleteMessage = view.findViewById(R.id.delete_message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -135,8 +135,8 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
avatarLayout.setVisibility(View.GONE);
|
avatarLayout.setVisibility(View.GONE);
|
||||||
sendInProgress.setVisibility(View.GONE);
|
sendInProgress.setVisibility(View.GONE);
|
||||||
downloadInProgress.setVisibility(View.GONE);
|
downloadInProgress.setVisibility(View.GONE);
|
||||||
pictures.setVisibility(View.GONE);
|
singleFileContent.setVisibility(View.GONE);
|
||||||
pictures.removeAllViews();
|
multiFileContents.setVisibility(View.GONE);
|
||||||
|
|
||||||
ChatMessage.State status = message.getState();
|
ChatMessage.State status = message.getState();
|
||||||
Address remoteSender = message.getFromAddress();
|
Address remoteSender = message.getFromAddress();
|
||||||
|
@ -174,7 +174,7 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
|
|
||||||
// Can't anchor incoming messages, setting this to align max width with LIME icon
|
// Can't anchor incoming messages, setting this to align max width with LIME icon
|
||||||
bubbleLayout.setPadding(
|
bubbleLayout.setPadding(
|
||||||
0, 0, (int) ImageUtils.dpToPixels(LinphoneActivity.instance(), 16), 0);
|
0, 0, (int) ImageUtils.dpToPixels(LinphoneActivity.instance(), 18), 0);
|
||||||
|
|
||||||
if (status == ChatMessage.State.InProgress) {
|
if (status == ChatMessage.State.InProgress) {
|
||||||
downloadInProgress.setVisibility(View.VISIBLE);
|
downloadInProgress.setVisibility(View.VISIBLE);
|
||||||
|
@ -217,87 +217,98 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileContents.size() > 0) {
|
if (fileContents.size() == 1) {
|
||||||
pictures.setVisibility(View.VISIBLE);
|
singleFileContent.setVisibility(View.VISIBLE);
|
||||||
|
displayContent(message, fileContents.get(0), singleFileContent, false);
|
||||||
|
} else if (fileContents.size() > 1) {
|
||||||
|
multiFileContents.removeAllViews();
|
||||||
|
multiFileContents.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
for (Content c : fileContents) {
|
for (Content c : fileContents) {
|
||||||
View content =
|
View content =
|
||||||
LayoutInflater.from(mContext)
|
LayoutInflater.from(mContext)
|
||||||
.inflate(R.layout.chat_bubble_content, null, false);
|
.inflate(R.layout.chat_bubble_content, null, false);
|
||||||
|
|
||||||
if (c.isFile() || (c.isFileTransfer() && message.isOutgoing())) {
|
displayContent(message, c, content, true);
|
||||||
// If message is outgoing, even if content
|
|
||||||
// is file transfer we have the file available
|
|
||||||
String filePath = c.getFilePath();
|
|
||||||
|
|
||||||
View v;
|
multiFileContents.addView(content);
|
||||||
if (FileUtils.isExtensionImage(filePath)) {
|
}
|
||||||
if (fileContents.size() == 1
|
}
|
||||||
&& mContext.getResources()
|
}
|
||||||
.getBoolean(
|
|
||||||
R.bool.use_big_pictures_to_preview_images_file_transfers)) {
|
private void displayContent(
|
||||||
v = content.findViewById(R.id.bigImage);
|
final ChatMessage message, Content c, View content, boolean isMultiContent) {
|
||||||
loadBitmap(c.getFilePath(), ((ImageView) v));
|
Button download = content.findViewById(R.id.download);
|
||||||
} else {
|
download.setVisibility(View.GONE);
|
||||||
v = content.findViewById(R.id.image);
|
|
||||||
loadBitmap(c.getFilePath(), ((ImageView) v));
|
if (c.isFile() || (c.isFileTransfer() && message.isOutgoing())) {
|
||||||
}
|
// If message is outgoing, even if content
|
||||||
} else {
|
// is file transfer we have the file available
|
||||||
v = content.findViewById(R.id.file);
|
final String filePath = c.getFilePath();
|
||||||
((TextView) v).setText(FileUtils.getNameFromFilePath(filePath));
|
|
||||||
}
|
View v;
|
||||||
v.setVisibility(View.VISIBLE);
|
if (FileUtils.isExtensionImage(filePath)) {
|
||||||
v.setTag(c.getFilePath());
|
if (!isMultiContent
|
||||||
v.setOnClickListener(
|
&& mContext.getResources()
|
||||||
new View.OnClickListener() {
|
.getBoolean(
|
||||||
@Override
|
R.bool.use_big_pictures_to_preview_images_file_transfers)) {
|
||||||
public void onClick(View v) {
|
v = content.findViewById(R.id.bigImage);
|
||||||
openFile((String) v.getTag());
|
loadBitmap(c.getFilePath(), ((ImageView) v));
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
Button download = content.findViewById(R.id.download);
|
v = content.findViewById(R.id.image);
|
||||||
download.setVisibility(View.VISIBLE);
|
loadBitmap(c.getFilePath(), ((ImageView) v));
|
||||||
|
}
|
||||||
if (mContext.getPackageManager()
|
} else {
|
||||||
.checkPermission(
|
v = content.findViewById(R.id.file);
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
((TextView) v).setText(FileUtils.getNameFromFilePath(filePath));
|
||||||
mContext.getPackageName())
|
}
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
v.setVisibility(View.VISIBLE);
|
||||||
String filename = c.getName();
|
v.setOnClickListener(
|
||||||
File file = new File(FileUtils.getStorageDirectory(mContext), filename);
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
int prefix = 1;
|
public void onClick(View v) {
|
||||||
while (file.exists()) {
|
openFile(filePath);
|
||||||
file =
|
|
||||||
new File(
|
|
||||||
FileUtils.getStorageDirectory(mContext),
|
|
||||||
prefix + "_" + filename);
|
|
||||||
Log.w(
|
|
||||||
"File with that name already exists, renamed to "
|
|
||||||
+ prefix
|
|
||||||
+ "_"
|
|
||||||
+ filename);
|
|
||||||
prefix += 1;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
download.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
download.setTag(c);
|
if (mContext.getPackageManager()
|
||||||
c.setFilePath(file.getPath());
|
.checkPermission(
|
||||||
download.setOnClickListener(
|
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
new View.OnClickListener() {
|
mContext.getPackageName())
|
||||||
@Override
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
public void onClick(View v) {
|
String filename = c.getName();
|
||||||
Content c = (Content) v.getTag();
|
File file = new File(FileUtils.getStorageDirectory(mContext), filename);
|
||||||
message.downloadContent(c);
|
|
||||||
}
|
int prefix = 1;
|
||||||
});
|
while (file.exists()) {
|
||||||
} else {
|
file =
|
||||||
Log.w(
|
new File(
|
||||||
"WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file");
|
FileUtils.getStorageDirectory(mContext),
|
||||||
LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
|
prefix + "_" + filename);
|
||||||
}
|
Log.w(
|
||||||
|
"File with that name already exists, renamed to "
|
||||||
|
+ prefix
|
||||||
|
+ "_"
|
||||||
|
+ filename);
|
||||||
|
prefix += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pictures.addView(content);
|
download.setTag(c);
|
||||||
|
c.setFilePath(file.getPath());
|
||||||
|
download.setOnClickListener(
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Content c = (Content) v.getTag();
|
||||||
|
message.downloadContent(c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Log.w(
|
||||||
|
"WRITE_EXTERNAL_STORAGE permission not granted, won't be able to store the downloaded file");
|
||||||
|
LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,30 +106,29 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
|
||||||
public void onBindViewHolder(@NonNull ChatMessageViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ChatMessageViewHolder holder, int position) {
|
||||||
EventLog event = mHistory.get(position);
|
EventLog event = mHistory.get(position);
|
||||||
|
|
||||||
holder.deleteEvent.setVisibility(View.GONE);
|
holder.delete.setVisibility(View.GONE);
|
||||||
holder.deleteMessage.setVisibility(View.GONE);
|
|
||||||
holder.eventLayout.setVisibility(View.GONE);
|
holder.eventLayout.setVisibility(View.GONE);
|
||||||
holder.securityEventLayout.setVisibility(View.GONE);
|
holder.securityEventLayout.setVisibility(View.GONE);
|
||||||
holder.rightAnchor.setVisibility(View.GONE);
|
holder.rightAnchor.setVisibility(View.GONE);
|
||||||
holder.bubbleLayout.setVisibility(View.GONE);
|
holder.bubbleLayout.setVisibility(View.GONE);
|
||||||
holder.sendInProgress.setVisibility(View.GONE);
|
holder.sendInProgress.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if (isEditionEnabled()) {
|
||||||
|
holder.delete.setVisibility(View.VISIBLE);
|
||||||
|
holder.delete.setChecked(isSelected(position));
|
||||||
|
holder.delete.setTag(position);
|
||||||
|
}
|
||||||
|
|
||||||
if (event.getType() == EventLog.Type.ConferenceChatMessage) {
|
if (event.getType() == EventLog.Type.ConferenceChatMessage) {
|
||||||
ChatMessage message = event.getChatMessage();
|
ChatMessage message = event.getChatMessage();
|
||||||
|
|
||||||
if (isEditionEnabled()) {
|
|
||||||
holder.deleteMessage.setVisibility(View.VISIBLE);
|
|
||||||
holder.deleteMessage.setChecked(isSelected(position));
|
|
||||||
holder.deleteMessage.setTag(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((message.isOutgoing() && message.getState() != ChatMessage.State.Displayed)
|
if ((message.isOutgoing() && message.getState() != ChatMessage.State.Displayed)
|
||||||
|| (!message.isOutgoing() && message.isFileTransfer())) {
|
|| (!message.isOutgoing() && message.isFileTransfer())) {
|
||||||
if (!mTransientMessages.contains(message)) {
|
if (!mTransientMessages.contains(message)) {
|
||||||
mTransientMessages.add(message);
|
mTransientMessages.add(message);
|
||||||
}
|
}
|
||||||
message.setUserData(
|
// This only works if JAVA object is kept, hence the transient list
|
||||||
holder); // This only works if JAVA object is kept, hence the transient list
|
message.setUserData(holder);
|
||||||
message.addListener(mListener);
|
message.addListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,12 +145,6 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
|
||||||
holder.bindMessage(message, contact);
|
holder.bindMessage(message, contact);
|
||||||
changeBackgroundDependingOnPreviousAndNextEvents(message, holder, position);
|
changeBackgroundDependingOnPreviousAndNextEvents(message, holder, position);
|
||||||
} else { // Event is not chat message
|
} else { // Event is not chat message
|
||||||
if (isEditionEnabled()) {
|
|
||||||
holder.deleteEvent.setVisibility(View.VISIBLE);
|
|
||||||
holder.deleteEvent.setChecked(isSelected(position));
|
|
||||||
holder.deleteEvent.setTag(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
Address address = event.getParticipantAddress();
|
Address address = event.getParticipantAddress();
|
||||||
if (address == null && event.getType() == EventLog.Type.ConferenceSecurityEvent) {
|
if (address == null && event.getType() == EventLog.Type.ConferenceSecurityEvent) {
|
||||||
address = event.getSecurityEventFaultyDeviceAddress();
|
address = event.getSecurityEventFaultyDeviceAddress();
|
||||||
|
|
|
@ -152,8 +152,7 @@ public class ImdnFragment extends Fragment {
|
||||||
LinphoneContact contact =
|
LinphoneContact contact =
|
||||||
ContactsManager.getInstance().findContactFromAddress(remoteSender);
|
ContactsManager.getInstance().findContactFromAddress(remoteSender);
|
||||||
|
|
||||||
mBubble.deleteMessage.setVisibility(View.GONE);
|
mBubble.delete.setVisibility(View.GONE);
|
||||||
mBubble.deleteEvent.setVisibility(View.GONE);
|
|
||||||
mBubble.eventLayout.setVisibility(View.GONE);
|
mBubble.eventLayout.setVisibility(View.GONE);
|
||||||
mBubble.securityEventLayout.setVisibility(View.GONE);
|
mBubble.securityEventLayout.setVisibility(View.GONE);
|
||||||
mBubble.rightAnchor.setVisibility(View.GONE);
|
mBubble.rightAnchor.setVisibility(View.GONE);
|
||||||
|
|
|
@ -194,8 +194,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/top"
|
android:layout_below="@id/top"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginRight="6dp"
|
android:layout_marginRight="8dp"
|
||||||
android:src="@drawable/security_alert_indicator" />
|
android:src="@drawable/security_alert_indicator" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/rightAnchor"
|
android:id="@+id/rightAnchor"
|
||||||
android:layout_width="1dp"
|
android:layout_width="3dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentRight="true"/>
|
android:layout_alignParentRight="true"/>
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/delete_event"
|
android:id="@+id/delete_event"
|
||||||
android:layout_width="30dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="30dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
|
@ -90,13 +90,24 @@
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/pictures"
|
android:id="@+id/multi_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="5dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="5dp"
|
||||||
app:flexWrap="wrap" />
|
app:flexWrap="wrap" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/single_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp">
|
||||||
|
|
||||||
|
<include layout="@layout/chat_bubble_content" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<org.linphone.views.MultiLineWrapContentWidthTextView
|
<org.linphone.views.MultiLineWrapContentWidthTextView
|
||||||
android:id="@+id/message"
|
android:id="@+id/message"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -140,17 +151,6 @@
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
android:textAppearance="@style/chat_bubble_time_font" />
|
android:textAppearance="@style/chat_bubble_time_font" />
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/delete_message"
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="30dp"
|
|
||||||
android:layout_alignTop="@id/background"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:button="@drawable/checkbox"
|
|
||||||
android:clickable="false"
|
|
||||||
android:contentDescription="@string/content_description_delete" />
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@id/imdn"
|
android:id="@id/imdn"
|
||||||
android:layout_width="10dp"
|
android:layout_width="10dp"
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="100dp"
|
||||||
android:maxHeight="100dp"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
@ -15,8 +14,7 @@
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/bigImage"
|
android:id="@+id/bigImage"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="200dp"
|
||||||
android:maxHeight="300dp"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
Loading…
Reference in a new issue