Improved chat message display

This commit is contained in:
Sylvain Berfini 2019-02-21 17:13:36 +01:00
parent 15ab10b4cb
commit f110e817d5
6 changed files with 119 additions and 118 deletions

View file

@ -76,10 +76,10 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
public final ImageView outgoingImdn;
public final TextView messageText;
public final FlexboxLayout pictures;
public final FlexboxLayout multiFileContents;
public final RelativeLayout singleFileContent;
public final CheckBox deleteEvent;
public final CheckBox deleteMessage;
public final CheckBox delete;
private Context mContext;
private ChatMessageViewHolderClickListener mListener;
@ -111,10 +111,10 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
outgoingImdn = view.findViewById(R.id.imdn);
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);
deleteMessage = view.findViewById(R.id.delete_message);
delete = view.findViewById(R.id.delete_event);
}
@Override
@ -135,8 +135,8 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
avatarLayout.setVisibility(View.GONE);
sendInProgress.setVisibility(View.GONE);
downloadInProgress.setVisibility(View.GONE);
pictures.setVisibility(View.GONE);
pictures.removeAllViews();
singleFileContent.setVisibility(View.GONE);
multiFileContents.setVisibility(View.GONE);
ChatMessage.State status = message.getState();
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
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) {
downloadInProgress.setVisibility(View.VISIBLE);
@ -217,87 +217,98 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
}
}
if (fileContents.size() > 0) {
pictures.setVisibility(View.VISIBLE);
if (fileContents.size() == 1) {
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) {
View content =
LayoutInflater.from(mContext)
.inflate(R.layout.chat_bubble_content, null, false);
if (c.isFile() || (c.isFileTransfer() && message.isOutgoing())) {
// If message is outgoing, even if content
// is file transfer we have the file available
String filePath = c.getFilePath();
displayContent(message, c, content, true);
View v;
if (FileUtils.isExtensionImage(filePath)) {
if (fileContents.size() == 1
&& mContext.getResources()
.getBoolean(
R.bool.use_big_pictures_to_preview_images_file_transfers)) {
v = content.findViewById(R.id.bigImage);
loadBitmap(c.getFilePath(), ((ImageView) v));
} else {
v = content.findViewById(R.id.image);
loadBitmap(c.getFilePath(), ((ImageView) v));
}
} else {
v = content.findViewById(R.id.file);
((TextView) v).setText(FileUtils.getNameFromFilePath(filePath));
}
v.setVisibility(View.VISIBLE);
v.setTag(c.getFilePath());
v.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
openFile((String) v.getTag());
}
});
multiFileContents.addView(content);
}
}
}
private void displayContent(
final ChatMessage message, Content c, View content, boolean isMultiContent) {
Button download = content.findViewById(R.id.download);
download.setVisibility(View.GONE);
if (c.isFile() || (c.isFileTransfer() && message.isOutgoing())) {
// If message is outgoing, even if content
// is file transfer we have the file available
final String filePath = c.getFilePath();
View v;
if (FileUtils.isExtensionImage(filePath)) {
if (!isMultiContent
&& mContext.getResources()
.getBoolean(
R.bool.use_big_pictures_to_preview_images_file_transfers)) {
v = content.findViewById(R.id.bigImage);
loadBitmap(c.getFilePath(), ((ImageView) v));
} else {
Button download = content.findViewById(R.id.download);
download.setVisibility(View.VISIBLE);
if (mContext.getPackageManager()
.checkPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
mContext.getPackageName())
== PackageManager.PERMISSION_GRANTED) {
String filename = c.getName();
File file = new File(FileUtils.getStorageDirectory(mContext), filename);
int prefix = 1;
while (file.exists()) {
file =
new File(
FileUtils.getStorageDirectory(mContext),
prefix + "_" + filename);
Log.w(
"File with that name already exists, renamed to "
+ prefix
+ "_"
+ filename);
prefix += 1;
v = content.findViewById(R.id.image);
loadBitmap(c.getFilePath(), ((ImageView) v));
}
} else {
v = content.findViewById(R.id.file);
((TextView) v).setText(FileUtils.getNameFromFilePath(filePath));
}
v.setVisibility(View.VISIBLE);
v.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
openFile(filePath);
}
});
} else {
download.setVisibility(View.VISIBLE);
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();
}
if (mContext.getPackageManager()
.checkPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
mContext.getPackageName())
== PackageManager.PERMISSION_GRANTED) {
String filename = c.getName();
File file = new File(FileUtils.getStorageDirectory(mContext), filename);
int prefix = 1;
while (file.exists()) {
file =
new File(
FileUtils.getStorageDirectory(mContext),
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();
}
}
}

View file

@ -106,30 +106,29 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
public void onBindViewHolder(@NonNull ChatMessageViewHolder holder, int position) {
EventLog event = mHistory.get(position);
holder.deleteEvent.setVisibility(View.GONE);
holder.deleteMessage.setVisibility(View.GONE);
holder.delete.setVisibility(View.GONE);
holder.eventLayout.setVisibility(View.GONE);
holder.securityEventLayout.setVisibility(View.GONE);
holder.rightAnchor.setVisibility(View.GONE);
holder.bubbleLayout.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) {
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)
|| (!message.isOutgoing() && message.isFileTransfer())) {
if (!mTransientMessages.contains(message)) {
mTransientMessages.add(message);
}
message.setUserData(
holder); // This only works if JAVA object is kept, hence the transient list
// This only works if JAVA object is kept, hence the transient list
message.setUserData(holder);
message.addListener(mListener);
}
@ -146,12 +145,6 @@ public class ChatMessagesAdapter extends SelectableAdapter<ChatMessageViewHolder
holder.bindMessage(message, contact);
changeBackgroundDependingOnPreviousAndNextEvents(message, holder, position);
} 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();
if (address == null && event.getType() == EventLog.Type.ConferenceSecurityEvent) {
address = event.getSecurityEventFaultyDeviceAddress();

View file

@ -152,8 +152,7 @@ public class ImdnFragment extends Fragment {
LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(remoteSender);
mBubble.deleteMessage.setVisibility(View.GONE);
mBubble.deleteEvent.setVisibility(View.GONE);
mBubble.delete.setVisibility(View.GONE);
mBubble.eventLayout.setVisibility(View.GONE);
mBubble.securityEventLayout.setVisibility(View.GONE);
mBubble.rightAnchor.setVisibility(View.GONE);

View file

@ -194,8 +194,8 @@
android:layout_height="wrap_content"
android:layout_below="@id/top"
android:layout_alignParentRight="true"
android:layout_marginTop="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:src="@drawable/security_alert_indicator" />
</RelativeLayout>

View file

@ -5,15 +5,15 @@
<View
android:id="@+id/rightAnchor"
android:layout_width="1dp"
android:layout_width="3dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"/>
<CheckBox
android:id="@+id/delete_event"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:adjustViewBounds="true"
@ -90,13 +90,24 @@
<com.google.android.flexbox.FlexboxLayout
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_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
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
android:id="@+id/message"
android:layout_width="wrap_content"
@ -140,17 +151,6 @@
android:gravity="right"
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
android:id="@id/imdn"
android:layout_width="10dp"

View file

@ -6,8 +6,7 @@
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="100dp"
android:layout_height="100dp"
android:layout_margin="5dp"
android:adjustViewBounds="true"
android:visibility="gone" />
@ -15,8 +14,7 @@
<ImageView
android:id="@+id/bigImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="300dp"
android:layout_height="200dp"
android:layout_margin="5dp"
android:adjustViewBounds="true"
android:visibility="gone" />