added download button for images not accepted automatically

Daniel Gultsch created

Change summary

src/eu/siacs/conversations/entities/Message.java                  | 13 
src/eu/siacs/conversations/services/XmppConnectionService.java    |  3 
src/eu/siacs/conversations/ui/ConversationFragment.java           | 38 
src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java      | 38 
src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java |  2 
5 files changed, 78 insertions(+), 16 deletions(-)

Detailed changes

src/eu/siacs/conversations/entities/Message.java 🔗

@@ -1,5 +1,6 @@
 package eu.siacs.conversations.entities;
 
+import eu.siacs.conversations.xmpp.jingle.JingleConnection;
 import android.content.ContentValues;
 import android.database.Cursor;
 
@@ -9,6 +10,7 @@ public class Message extends AbstractEntity {
 	
 	public static final String TABLENAME = "messages";
 
+	public static final int STATUS_RECEIVED_OFFER = -2;
 	public static final int STATUS_RECIEVING = -1;
 	public static final int STATUS_RECIEVED = 0;
 	public static final int STATUS_UNSEND = 1;
@@ -16,6 +18,7 @@ public class Message extends AbstractEntity {
 	public static final int STATUS_SEND_FAILED = 3;
 	public static final int STATUS_SEND_REJECTED = 4;
 	public static final int STATUS_PREPARING = 5;
+	public static final int STATUS_OFFERED = 6;
 
 	public static final int ENCRYPTION_NONE = 0;
 	public static final int ENCRYPTION_PGP = 1;
@@ -44,6 +47,8 @@ public class Message extends AbstractEntity {
 	protected boolean read = true;
 
 	protected transient Conversation conversation = null;
+	
+	protected transient JingleConnection jingleConnection = null;
 
 	public Message(Conversation conversation, String body, int encryption) {
 		this(java.util.UUID.randomUUID().toString(), conversation.getUuid(),
@@ -173,4 +178,12 @@ public class Message extends AbstractEntity {
 	public void setPresence(String presence) {
 		this.counterpart = this.counterpart.split("/")[0] + "/" + presence;
 	}
+	
+	public void setJingleConnection(JingleConnection connection) {
+		this.jingleConnection = connection;
+	}
+	
+	public JingleConnection getJingleConnection() {
+		return this.jingleConnection;
+	}
 }

src/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -423,8 +423,7 @@ public class XmppConnectionService extends Service {
 					convChangedListener.onConversationListChanged();
 				}
 				getFileBackend().copyImageToPrivateStorage(message, uri);
-				message.setStatus(Message.STATUS_UNSEND);
-				databaseBackend.createMessage(message);
+				message.setStatus(Message.STATUS_OFFERED);
 				if (convChangedListener!=null) {
 					convChangedListener.onConversationListChanged();
 				}

src/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -21,6 +21,7 @@ import eu.siacs.conversations.entities.MucOptions;
 import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
 import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xmpp.jingle.JingleConnection;
 import android.app.AlertDialog;
 import android.app.Fragment;
 import android.content.Context;
@@ -42,6 +43,7 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
+import android.widget.Button;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ListView;
@@ -217,6 +219,8 @@ public class ConversationFragment extends Fragment {
 						viewHolder.contact_picture = (ImageView) view
 								.findViewById(R.id.message_photo);
 						
+						viewHolder.download_button = (Button) view.findViewById(R.id.download_button);
+						
 						if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
 
 							viewHolder.contact_picture.setImageBitmap(mBitmapCache
@@ -265,19 +269,33 @@ public class ConversationFragment extends Fragment {
 				
 				
 				if (item.getType() == Message.TYPE_IMAGE) {
-					if (item.getStatus() == Message.STATUS_PREPARING) {
+					if ((item.getStatus() == Message.STATUS_PREPARING)||(item.getStatus() == Message.STATUS_RECIEVING)) {
 						viewHolder.image.setVisibility(View.GONE);
 						viewHolder.messageBody.setVisibility(View.VISIBLE);
-						viewHolder.messageBody.setText(getString(R.string.preparing_image));
+						if (item.getStatus() == Message.STATUS_PREPARING) {
+							viewHolder.messageBody.setText(getString(R.string.preparing_image));
+						} else if (item.getStatus() == Message.STATUS_RECIEVING) {
+							viewHolder.download_button.setVisibility(View.GONE);
+							viewHolder.messageBody.setText(getString(R.string.receiving_image));
+						}
 						viewHolder.messageBody.setTextColor(0xff33B5E5);
 						viewHolder.messageBody.setTypeface(null,Typeface.ITALIC);
-					} else if (item.getStatus() == Message.STATUS_RECIEVING) {
+					} else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) {
 						viewHolder.image.setVisibility(View.GONE);
 						viewHolder.messageBody.setVisibility(View.GONE);
-						viewHolder.messageBody.setVisibility(View.VISIBLE);
-						viewHolder.messageBody.setText(getString(R.string.receiving_image));
-						viewHolder.messageBody.setTextColor(0xff33B5E5);
-						viewHolder.messageBody.setTypeface(null,Typeface.ITALIC);
+						viewHolder.download_button.setVisibility(View.VISIBLE);
+						viewHolder.download_button.setOnClickListener(new OnClickListener() {
+							
+							@Override
+							public void onClick(View v) {
+								JingleConnection connection = item.getJingleConnection();
+								if (connection!=null) {
+									connection.accept();
+								} else {
+									Log.d("xmppService","attached jingle connection was null");
+								}
+							}
+						});
 					} else {
 						try {
 							Bitmap thumbnail = activity.xmppConnectionService.getFileBackend().getThumbnailFromMessage(item,(int) (metrics.density * 288));
@@ -331,6 +349,11 @@ public class ConversationFragment extends Fragment {
 					viewHolder.time.setTextColor(0xFF8e8e8e);
 					viewHolder.time.setText("sending\u2026");
 					break;
+				case Message.STATUS_OFFERED:
+					viewHolder.time.setTypeface(null, Typeface.ITALIC);
+					viewHolder.time.setTextColor(0xFF8e8e8e);
+					viewHolder.time.setText("offering\u2026");
+					break;
 				case Message.STATUS_SEND_FAILED:
 					viewHolder.time.setText(getString(R.string.send_failed) + " \u00B7 " + UIHelper.readableTimeDifference(item
 							.getTimeSent()));
@@ -636,6 +659,7 @@ public class ConversationFragment extends Fragment {
 
 	private static class ViewHolder {
 
+		protected Button download_button;
 		protected ImageView image;
 		protected ImageView indicator;
 		protected TextView time;

src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java 🔗

@@ -50,6 +50,8 @@ public class JingleConnection {
 	private boolean receivedCandidate = false;
 	private boolean sentCandidate = false;
 	
+	private boolean acceptedAutomatically = false;
+	
 	private JingleTransport transport = null;
 	
 	private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
@@ -69,8 +71,12 @@ public class JingleConnection {
 		public void onFileTransmitted(JingleFile file) {
 			if (responder.equals(account.getFullJid())) {
 				sendSuccess();
+				if (acceptedAutomatically) {
+					message.markUnread();
+				}
 				mXmppConnectionService.markMessage(message, Message.STATUS_RECIEVED);
 			}
+			mXmppConnectionService.databaseBackend.createMessage(message);
 			Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum());
 		}
 	};
@@ -126,7 +132,7 @@ public class JingleConnection {
 				this.cancel();
 			}
 			} else if (packet.isAction("session-accept")) {
-			accept(packet);
+			receiveAccept(packet);
 		} else if (packet.isAction("transport-info")) {
 			receiveTransportInfo(packet);
 		} else if (packet.isAction("transport-replace")) {
@@ -189,7 +195,8 @@ public class JingleConnection {
 		Conversation conversation = this.mXmppConnectionService.findOrCreateConversation(account, packet.getFrom().split("/")[0], false);
 		this.message = new Message(conversation, "receiving image file", Message.ENCRYPTION_NONE);
 		this.message.setType(Message.TYPE_IMAGE);
-		this.message.setStatus(Message.STATUS_RECIEVING);
+		this.message.setStatus(Message.STATUS_RECEIVED_OFFER);
+		this.message.setJingleConnection(this);
 		String[] fromParts = packet.getFrom().split("/");
 		this.message.setPresence(fromParts[1]);
 		this.account = account;
@@ -206,15 +213,16 @@ public class JingleConnection {
 			Element fileName = fileOffer.findChild("name");
 			this.file.setExpectedSize(Long.parseLong(fileSize.getContent()));
 			conversation.getMessages().add(message);
-			this.mXmppConnectionService.databaseBackend.createMessage(message);
-			if (this.mXmppConnectionService.convChangedListener!=null) {
-				this.mXmppConnectionService.convChangedListener.onConversationListChanged();
-			}
 			if (this.file.getExpectedSize()<=this.mJingleConnectionManager.getAutoAcceptFileSize()) {
 				Log.d("xmppService","auto accepting file from "+packet.getFrom());
+				this.acceptedAutomatically = true;
 				this.sendAccept();
 			} else {
+				message.markUnread();
 				Log.d("xmppService","not auto accepting new file offer with size: "+this.file.getExpectedSize()+" allowed size:"+this.mJingleConnectionManager.getAutoAcceptFileSize());
+				if (this.mXmppConnectionService.convChangedListener!=null) {
+					this.mXmppConnectionService.convChangedListener.onConversationListChanged();
+				}
 			}
 		} else {
 			Log.d("xmppService","no file offer was attached. aborting");
@@ -249,6 +257,7 @@ public class JingleConnection {
 	
 	private void sendAccept() {
 		status = STATUS_ACCEPTED;
+		mXmppConnectionService.markMessage(message, Message.STATUS_RECIEVING);
 		this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() {
 			
 			@Override
@@ -308,10 +317,11 @@ public class JingleConnection {
 		account.getXmppConnection().sendIqPacket(packet,responseListener);
 	}
 	
-	private void accept(JinglePacket packet) {
+	private void receiveAccept(JinglePacket packet) {
 		Content content = packet.getJingleContent();
 		mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
 		this.status = STATUS_ACCEPTED;
+		mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
 		this.connectNextCandidate();
 		IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
 		account.getXmppConnection().sendIqPacket(response, null);
@@ -639,4 +649,18 @@ public class JingleConnection {
 	public JingleTransport getTransport() {
 		return this.transport;
 	}
+
+	public void accept() {
+		if (status==STATUS_INITIATED) {
+			new Thread(new Runnable() {
+				
+				@Override
+				public void run() {
+					sendAccept();
+				}
+			}).start();
+		} else {
+			Log.d("xmppService","status ("+status+") was not ok");
+		}
+	}
 }

src/eu/siacs/conversations/xmpp/jingle/JingleInbandTransport.java 🔗

@@ -120,6 +120,7 @@ public class JingleInbandTransport extends JingleTransport {
 			int count = fileInputStream.read(buffer);
 			if (count==-1) {
 				file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
+				fileInputStream.close();
 				this.onFileTransmitted.onFileTransmitted(file);
 			} else {
 				this.digest.update(buffer);
@@ -155,6 +156,7 @@ public class JingleInbandTransport extends JingleTransport {
 				file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
 				Log.d("xmppService","file name: "+file.getAbsolutePath());
 				fileOutputStream.flush();
+				fileOutputStream.close();
 				this.onFileTransmitted.onFileTransmitted(file);
 			}
 		} catch (IOException e) {