reworked message preview / message meta information (ie file offered, received * file)

Daniel Gultsch created

fixed #837

Change summary

src/main/java/eu/siacs/conversations/services/NotificationService.java   |  41 
src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java | 123 
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java      |  52 
src/main/java/eu/siacs/conversations/utils/UIHelper.java                 | 110 
src/main/res/values/strings.xml                                          |  13 
5 files changed, 171 insertions(+), 168 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/services/NotificationService.java 🔗

@@ -40,6 +40,7 @@ import eu.siacs.conversations.entities.Message;
 import eu.siacs.conversations.ui.ConversationActivity;
 import eu.siacs.conversations.ui.ManageAccountActivity;
 import eu.siacs.conversations.ui.TimePreference;
+import eu.siacs.conversations.utils.UIHelper;
 
 public class NotificationService {
 
@@ -210,7 +211,7 @@ public class NotificationService {
 				conversation = messages.get(0).getConversation();
 				String name = conversation.getName();
 				style.addLine(Html.fromHtml("<b>" + name + "</b> "
-							+ getReadableBody(messages.get(0))));
+							+ UIHelper.getMessagePreview(mXmppConnectionService,messages.get(0)).first));
 				names.append(name);
 				names.append(", ");
 			}
@@ -268,7 +269,7 @@ public class NotificationService {
 			bigPictureStyle.bigPicture(bitmap);
 			if (tmp.size() > 0) {
 				bigPictureStyle.setSummaryText(getMergedBodies(tmp));
-				builder.setContentText(getReadableBody(tmp.get(0)));
+				builder.setContentText(UIHelper.getMessagePreview(mXmppConnectionService,tmp.get(0)).first);
 			} else {
 				builder.setContentText(mXmppConnectionService.getString(R.string.image_file));
 			}
@@ -280,11 +281,10 @@ public class NotificationService {
 
 	private void modifyForTextOnly(final Builder builder,
 			final ArrayList<Message> messages, final boolean notify) {
-		builder.setStyle(new NotificationCompat.BigTextStyle()
-				.bigText(getMergedBodies(messages)));
-		builder.setContentText(getReadableBody(messages.get(0)));
+		builder.setStyle(new NotificationCompat.BigTextStyle().bigText(getMergedBodies(messages)));
+		builder.setContentText(UIHelper.getMessagePreview(mXmppConnectionService,messages.get(0)).first);
 		if (notify) {
-			builder.setTicker(getReadableBody(messages.get(messages.size() - 1)));
+			builder.setTicker(UIHelper.getMessagePreview(mXmppConnectionService,messages.get(messages.size() - 1)).first);
 		}
 	}
 
@@ -302,7 +302,7 @@ public class NotificationService {
 	private String getMergedBodies(final ArrayList<Message> messages) {
 		final StringBuilder text = new StringBuilder();
 		for (int i = 0; i < messages.size(); ++i) {
-			text.append(getReadableBody(messages.get(i)));
+			text.append(UIHelper.getMessagePreview(mXmppConnectionService,messages.get(i)).first);
 			if (i != messages.size() - 1) {
 				text.append("\n");
 			}
@@ -310,33 +310,6 @@ public class NotificationService {
 		return text.toString();
 	}
 
-	private String getReadableBody(final Message message) {
-		if (message.getDownloadable() != null
-				&& (message.getDownloadable().getStatus() == Downloadable.STATUS_OFFER || message
-					.getDownloadable().getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE)) {
-			if (message.getType() == Message.TYPE_FILE) {
-				return mXmppConnectionService.getString(R.string.file_offered_for_download);
-			} else {
-				return mXmppConnectionService.getText(
-						R.string.image_offered_for_download).toString();
-			}
-		} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
-			return mXmppConnectionService.getText(
-					R.string.encrypted_message_received).toString();
-		} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
-			return mXmppConnectionService.getText(R.string.decryption_failed)
-				.toString();
-		} else if (message.getType() == Message.TYPE_FILE) {
-			DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
-			return mXmppConnectionService.getString(R.string.file,file.getMimeType());
-		} else if (message.getType() == Message.TYPE_IMAGE) {
-			return mXmppConnectionService.getText(R.string.image_file)
-				.toString();
-		} else {
-			return message.getBody().trim();
-		}
-	}
-
 	private PendingIntent createContentIntent(final String conversationUuid) {
 		final TaskStackBuilder stackBuilder = TaskStackBuilder
 			.create(mXmppConnectionService);

src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java 🔗

@@ -3,6 +3,7 @@ package eu.siacs.conversations.ui.adapter;
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Typeface;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -34,10 +35,8 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
 	@Override
 	public View getView(int position, View view, ViewGroup parent) {
 		if (view == null) {
-			LayoutInflater inflater = (LayoutInflater) activity
-				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-			view = inflater.inflate(R.layout.conversation_list_row,
-					parent, false);
+			LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+			view = inflater.inflate(R.layout.conversation_list_row,parent, false);
 		}
 		Conversation conversation = getItem(position);
 		if (this.activity instanceof ConversationActivity) {
@@ -53,20 +52,15 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
 				view.setBackgroundColor(Color.TRANSPARENT);
 			}
 		}
-		TextView convName = (TextView) view
-			.findViewById(R.id.conversation_name);
-		if (conversation.getMode() == Conversation.MODE_SINGLE
-				|| activity.useSubjectToIdentifyConference()) {
+		TextView convName = (TextView) view.findViewById(R.id.conversation_name);
+		if (conversation.getMode() == Conversation.MODE_SINGLE || activity.useSubjectToIdentifyConference()) {
 			convName.setText(conversation.getName());
 		} else {
 			convName.setText(conversation.getJid().toBareJid().toString());
 		}
-		TextView mLastMessage = (TextView) view
-			.findViewById(R.id.conversation_lastmsg);
-		TextView mTimestamp = (TextView) view
-			.findViewById(R.id.conversation_lastupdate);
-		ImageView imagePreview = (ImageView) view
-			.findViewById(R.id.conversation_lastimage);
+		TextView mLastMessage = (TextView) view.findViewById(R.id.conversation_lastmsg);
+		TextView mTimestamp = (TextView) view.findViewById(R.id.conversation_lastupdate);
+		ImageView imagePreview = (ImageView) view.findViewById(R.id.conversation_lastimage);
 
 		Message message = conversation.getLatestMessage();
 
@@ -76,89 +70,36 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
 			convName.setTypeface(null, Typeface.NORMAL);
 		}
 
-		if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE
-				|| message.getDownloadable() != null) {
-			Downloadable d = message.getDownloadable();
-			if (conversation.isRead()) {
-				mLastMessage.setTypeface(null, Typeface.ITALIC);
-			} else {
-				mLastMessage.setTypeface(null, Typeface.BOLD_ITALIC);
-			}
-			if (d != null) {
-				mLastMessage.setVisibility(View.VISIBLE);
-				imagePreview.setVisibility(View.GONE);
-				if (d.getStatus() == Downloadable.STATUS_CHECKING) {
-					mLastMessage.setText(R.string.checking_image);
-				} else if (d.getStatus() == Downloadable.STATUS_DOWNLOADING) {
-					if (message.getType() == Message.TYPE_FILE) {
-						mLastMessage.setText(getContext().getString(R.string.receiving_file,d.getMimeType(), d.getProgress()));
-					} else {
-						mLastMessage.setText(getContext().getString(R.string.receiving_image, d.getProgress()));
-					}
-				} else if (d.getStatus() == Downloadable.STATUS_OFFER) {
-					if (message.getType() == Message.TYPE_FILE) {
-						mLastMessage.setText(R.string.file_offered_for_download);
-					} else {
-						mLastMessage.setText(R.string.image_offered_for_download);
-					}
-				} else if (d.getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE) {
-					mLastMessage.setText(R.string.image_offered_for_download);
-				} else if (d.getStatus() == Downloadable.STATUS_DELETED) {
-					if (message.getType() == Message.TYPE_FILE) {
-						mLastMessage.setText(R.string.file_deleted);
-					} else {
-						mLastMessage.setText(R.string.image_file_deleted);
-					}
-				} else if (d.getStatus() == Downloadable.STATUS_FAILED) {
-					if (message.getType() == Message.TYPE_FILE) {
-						mLastMessage.setText(R.string.file_transmission_failed);
-					} else {
-						mLastMessage.setText(R.string.image_transmission_failed);
-					}
-				} else if (message.getImageParams().width > 0) {
-					mLastMessage.setVisibility(View.GONE);
-					imagePreview.setVisibility(View.VISIBLE);
-					activity.loadBitmap(message, imagePreview);
+		if (message.getImageParams().width > 0
+				&& (message.getDownloadable() == null
+				|| message.getDownloadable().getStatus() == Downloadable.STATUS_DELETED)) {
+			mLastMessage.setVisibility(View.GONE);
+			imagePreview.setVisibility(View.VISIBLE);
+			activity.loadBitmap(message, imagePreview);
+		} else {
+			Pair<String,Boolean> preview = UIHelper.getMessagePreview(activity,message);
+			mLastMessage.setVisibility(View.VISIBLE);
+			imagePreview.setVisibility(View.GONE);
+			mLastMessage.setText(preview.first);
+			if (preview.second) {
+				if (conversation.isRead()) {
+					mLastMessage.setTypeface(null, Typeface.ITALIC);
 				} else {
-					mLastMessage.setText("");
+					mLastMessage.setTypeface(null,Typeface.BOLD_ITALIC);
 				}
-			} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
-				imagePreview.setVisibility(View.GONE);
-				mLastMessage.setVisibility(View.VISIBLE);
-				mLastMessage.setText(R.string.encrypted_message_received);
-			} else if (message.getType() == Message.TYPE_FILE && message.getImageParams().width <= 0) {
-				DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message);
-				mLastMessage.setVisibility(View.VISIBLE);
-				imagePreview.setVisibility(View.GONE);
-				mLastMessage.setText(getContext().getString(R.string.file,file.getMimeType()));
-			} else {
-				mLastMessage.setVisibility(View.GONE);
-				imagePreview.setVisibility(View.VISIBLE);
-				activity.loadBitmap(message, imagePreview);
-			}
-		} else {
-			if ((message.getEncryption() != Message.ENCRYPTION_PGP)
-					&& (message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED)) {
-				mLastMessage.setText(message.getBody());
-			} else {
-				mLastMessage.setText(R.string.encrypted_message_received);
-			}
-			if (!conversation.isRead()) {
-				mLastMessage.setTypeface(null, Typeface.BOLD);
 			} else {
-				mLastMessage.setTypeface(null, Typeface.NORMAL);
+				if (conversation.isRead()) {
+					mLastMessage.setTypeface(null,Typeface.NORMAL);
+				} else {
+					mLastMessage.setTypeface(null,Typeface.BOLD);
+				}
 			}
-			mLastMessage.setVisibility(View.VISIBLE);
-			imagePreview.setVisibility(View.GONE);
 		}
-		mTimestamp.setText(UIHelper.readableTimeDifference(getContext(),
-					conversation.getLatestMessage().getTimeSent()));
 
-		ImageView profilePicture = (ImageView) view
-			.findViewById(R.id.conversation_image);
-		profilePicture.setImageBitmap(activity.avatarService().get(
-					conversation, activity.getPixel(56)));
+		mTimestamp.setText(UIHelper.readableTimeDifference(activity,conversation.getLatestMessage().getTimeSent()));
+		ImageView profilePicture = (ImageView) view.findViewById(R.id.conversation_image);
+		profilePicture.setImageBitmap(activity.avatarService().get(conversation, activity.getPixel(56)));
 
 		return view;
 	}
-}
+}

src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -144,7 +144,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 				break;
 			default:
 				if (multiReceived) {
-					info = getMessageDisplayName(message);
+					info = UIHelper.getMessageDisplayName(message);
 				}
 				break;
 		}
@@ -213,24 +213,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		viewHolder.messageBody.setTextIsSelectable(false);
 	}
 
-	private String getMessageDisplayName(final Message message) {
-		if (message.getStatus() == Message.STATUS_RECEIVED) {
-			if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
-				return getDisplayedMucCounterpart(message.getCounterpart());
-			} else {
-				final Contact contact = message.getContact();
-				return contact != null ? contact.getDisplayName() : "";
-			}
-		} else {
-			if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
-				return getDisplayedMucCounterpart(message.getConversation().getJid());
-			} else {
-				final Jid jid = message.getConversation().getAccount().getJid();
-				return jid.hasLocalpart() ? jid.getLocalpart() : jid.toDomainJid().toString();
-			}
-		}
-	}
-
 	private void displayTextMessage(final ViewHolder viewHolder, final Message message) {
 		if (viewHolder.download_button != null) {
 			viewHolder.download_button.setVisibility(View.GONE);
@@ -238,7 +220,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		viewHolder.image.setVisibility(View.GONE);
 		viewHolder.messageBody.setVisibility(View.VISIBLE);
 		if (message.getBody() != null) {
-			final String nick = getMessageDisplayName(message);
+			final String nick = UIHelper.getMessageDisplayName(message);
 			final String formattedBody = message.getMergedBody().replaceAll("^/me ", nick + " ");
 			if (message.getType() != Message.TYPE_PRIVATE) {
 				if (message.hasMeCommand()) {
@@ -303,16 +285,15 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 	}
 
 	private void displayOpenableMessage(ViewHolder viewHolder,final Message message) {
-		final DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message);
 		viewHolder.image.setVisibility(View.GONE);
 		viewHolder.messageBody.setVisibility(View.GONE);
 		viewHolder.download_button.setVisibility(View.VISIBLE);
-		viewHolder.download_button.setText(activity.getString(R.string.open_file, file.getMimeType()));
+		viewHolder.download_button.setText(activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity,message)));
 		viewHolder.download_button.setOnClickListener(new OnClickListener() {
 
 			@Override
 			public void onClick(View v) {
-				openDownloadable(file);
+				openDownloadable(message);
 			}
 		});
 		viewHolder.download_button.setOnLongClickListener(openContextMenu);
@@ -352,16 +333,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		viewHolder.image.setOnLongClickListener(openContextMenu);
 	}
 
-	private String getDisplayedMucCounterpart(final Jid counterpart) {
-		if (counterpart==null) {
-			return "";
-		} else if (!counterpart.isBareJid()) {
-			return counterpart.getResourcepart();
-		} else {
-			return counterpart.toString();
-		}
-	}
-
 	@Override
 	public View getView(int position, View view, ViewGroup parent) {
 		final Message message = getItem(position);
@@ -481,8 +452,9 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 			if (contact != null) {
 				viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48)));
 			} else if (conversation.getMode() == Conversation.MODE_MULTI) {
-				viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(getDisplayedMucCounterpart(message.getCounterpart()),
-							activity.getPixel(48)));
+				viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(
+						UIHelper.getMessageDisplayName(message),
+						activity.getPixel(48)));
 			}
 		} else if (type == SENT) {
 			viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(account, activity.getPixel(48)));
@@ -519,7 +491,9 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 			Downloadable d = message.getDownloadable();
 			if (d.getStatus() == Downloadable.STATUS_DOWNLOADING) {
 				if (message.getType() == Message.TYPE_FILE) {
-					displayInfoMessage(viewHolder,activity.getString(R.string.receiving_file,d.getMimeType(),d.getProgress()));
+					displayInfoMessage(viewHolder,activity.getString(R.string.receiving_x_file,
+							UIHelper.getFileDescriptionString(activity,message),
+							d.getProgress()));
 				} else {
 					displayInfoMessage(viewHolder,activity.getString(R.string.receiving_image,d.getProgress()));
 				}
@@ -533,7 +507,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 				}
 			} else if (d.getStatus() == Downloadable.STATUS_OFFER) {
 				if (message.getType() == Message.TYPE_FILE) {
-					displayDownloadableMessage(viewHolder,message,activity.getString(R.string.download_file,d.getMimeType()));
+					displayDownloadableMessage(viewHolder,message,activity.getString(R.string.download_x_file,
+							UIHelper.getFileDescriptionString(activity,message)));
 				} else {
 					displayDownloadableMessage(viewHolder, message,activity.getString(R.string.download_image));
 				}
@@ -592,7 +567,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		}
 	}
 
-	public void openDownloadable(DownloadableFile file) {
+	public void openDownloadable(Message message) {
+		DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message);
 		if (!file.exists()) {
 			Toast.makeText(activity,R.string.file_deleted,Toast.LENGTH_SHORT).show();
 			return;

src/main/java/eu/siacs/conversations/utils/UIHelper.java 🔗

@@ -1,12 +1,20 @@
 package eu.siacs.conversations.utils;
 
+import java.net.URLConnection;
 import java.util.Calendar;
 import java.util.Date;
 
 import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.Downloadable;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.xmpp.jid.Jid;
+
 import android.content.Context;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
+import android.util.Pair;
 
 public class UIHelper {
 	private static final int SHORT_DATE_FLAGS = DateUtils.FORMAT_SHOW_DATE
@@ -102,4 +110,106 @@ public class UIHelper {
 				0xFF795548, 0xFF607d8b};
 		return colors[(int) ((name.hashCode() & 0xffffffffl) % colors.length)];
 	}
+
+	public static Pair<String,Boolean> getMessagePreview(final Context context, final Message message) {
+		final Downloadable d = message.getDownloadable();
+		if (d != null ) {
+			switch (d.getStatus()) {
+				case Downloadable.STATUS_CHECKING:
+					return new Pair<>(context.getString(R.string.checking_image),true);
+				case Downloadable.STATUS_DOWNLOADING:
+					if (message.getType() == Message.TYPE_FILE) {
+						return new Pair<>(context.getString(R.string.receiving_x_file,
+								getFileDescriptionString(context,message),
+								d.getProgress()),true);
+					} else {
+						return new Pair<>(context.getString(R.string.receiving_image, d.getProgress()),true);
+					}
+				case Downloadable.STATUS_OFFER:
+				case Downloadable.STATUS_OFFER_CHECK_FILESIZE:
+					if (message.getType() == Message.TYPE_FILE) {
+						return new Pair<>(context.getString(R.string.x_file_offered_for_download,
+								getFileDescriptionString(context,message)),true);
+					} else {
+						return new Pair<>(context.getString(R.string.image_offered_for_download),true);
+					}
+				case Downloadable.STATUS_DELETED:
+					if (message.getType() == Message.TYPE_FILE) {
+						return new Pair<>(context.getString(R.string.file_deleted),true);
+					} else {
+						return new Pair<>(context.getString(R.string.image_file_deleted),true);
+					}
+				case Downloadable.STATUS_FAILED:
+					if (message.getType() == Message.TYPE_FILE) {
+						return new Pair<>(context.getString(R.string.file_transmission_failed),true);
+					} else {
+						return new Pair<>(context.getString(R.string.image_transmission_failed),true);
+					}
+				default:
+					return new Pair<>("",false);
+			}
+		} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
+			return new Pair<>(context.getString(R.string.encrypted_message_received),true);
+		} else if (message.getType() == Message.TYPE_FILE) {
+			if (message.getStatus() == Message.STATUS_RECEIVED) {
+				return new Pair<>(context.getString(R.string.received_x_file,
+						getFileDescriptionString(context, message)), true);
+			} else {
+				return new Pair<>(getFileDescriptionString(context,message),true);
+			}
+		} else {
+			if (message.getBody().startsWith("/me ")) {
+				return new Pair<>(message.getBody().replaceAll("^/me ",UIHelper.getMessageDisplayName(message) + " "),false);
+			} else {
+				return new Pair<>(message.getBody(), false);
+			}
+		}
+	}
+
+	public static String getFileDescriptionString(final Context context, final Message message) {
+		final String path = message.getRelativeFilePath();
+		if (path == null) {
+			return "";
+		}
+		final String mime = URLConnection.guessContentTypeFromName(path);
+		if (mime == null) {
+			return "";
+		} else if (mime.startsWith("audio/")) {
+			return context.getString(R.string.audio);
+		} else if(mime.startsWith("video/")) {
+			return context.getString(R.string.video);
+		} else if (mime.contains("pdf")) {
+			return context.getString(R.string.pdf_document)	;
+		} else {
+			return mime;
+		}
+	}
+
+	public static String getMessageDisplayName(final Message message) {
+		if (message.getStatus() == Message.STATUS_RECEIVED) {
+			if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
+				return getDisplayedMucCounterpart(message.getCounterpart());
+			} else {
+				final Contact contact = message.getContact();
+				return contact != null ? contact.getDisplayName() : "";
+			}
+		} else {
+			if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
+				return getDisplayedMucCounterpart(message.getConversation().getJid());
+			} else {
+				final Jid jid = message.getConversation().getAccount().getJid();
+				return jid.hasLocalpart() ? jid.getLocalpart() : jid.toDomainJid().toString();
+			}
+		}
+	}
+
+	private static String getDisplayedMucCounterpart(final Jid counterpart) {
+		if (counterpart==null) {
+			return "";
+		} else if (!counterpart.isBareJid()) {
+			return counterpart.getResourcepart();
+		} else {
+			return counterpart.toString();
+		}
+	}
 }

src/main/res/values/strings.xml 🔗

@@ -362,13 +362,12 @@
     <string name="pref_keep_foreground_service">Keep service in foreground</string>
     <string name="pref_keep_foreground_service_summary">Prevents the operating system from killing your connection</string>
     <string name="choose_file">Choose file</string>
-    <string name="receiving_file">Receiving %1$s file (%2$d%% completed)</string>
-    <string name="download_file">Download %s file</string>
-    <string name="open_file">Open %s file</string>
+    <string name="receiving_x_file">Receiving %1$s (%2$d%% completed)</string>
+    <string name="download_x_file">Download %s</string>
+    <string name="open_x_file">Open %s</string>
     <string name="sending_file">sending (%1$d%% completed)</string>
     <string name="preparing_file">Preparing file for transmission</string>
-    <string name="file_offered_for_download">File offered for download</string>
-    <string name="file">%s file</string>
+    <string name="x_file_offered_for_download">%s offered for download</string>
     <string name="cancel_transmission">Cancel transmission</string>
     <string name="file_transmission_failed">file transmission failed</string>
     <string name="file_deleted">The file has been deleted</string>
@@ -437,4 +436,8 @@
 	<string name="pref_input_options">Input options</string>
 	<string name="pref_enter_is_send">Enter is send</string>
 	<string name="pref_enter_is_send_summary">Use enter key to send message</string>
+	<string name="audio">audio file</string>
+	<string name="video">video file</string>
+	<string name="pdf_document">PDF document</string>
+	<string name="received_x_file">Received %s</string>
 </resources>