Merge branch 'feature-gboardgifs' of https://github.com/illegalprime/Conversations into illegalprime-feature-gboardgifs
This commit is contained in:
		
						commit
						470d244414
					
				| @ -26,7 +26,7 @@ dependencies { | |||||||
|     playstoreCompile 'com.google.android.gms:play-services-gcm:9.4.0' |     playstoreCompile 'com.google.android.gms:play-services-gcm:9.4.0' | ||||||
|     compile 'org.sufficientlysecure:openpgp-api:10.0' |     compile 'org.sufficientlysecure:openpgp-api:10.0' | ||||||
|     compile 'com.soundcloud.android:android-crop:1.0.1@aar' |     compile 'com.soundcloud.android:android-crop:1.0.1@aar' | ||||||
|     compile 'com.android.support:support-v13:24.2.0' |     compile 'com.android.support:support-v13:25.1.0' | ||||||
|     compile 'org.bouncycastle:bcprov-jdk15on:1.52' |     compile 'org.bouncycastle:bcprov-jdk15on:1.52' | ||||||
|     compile 'org.bouncycastle:bcmail-jdk15on:1.52' |     compile 'org.bouncycastle:bcmail-jdk15on:1.52' | ||||||
|     compile 'org.jitsi:org.otr4j:0.22' |     compile 'org.jitsi:org.otr4j:0.22' | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ import eu.siacs.conversations.utils.CryptoHelper; | |||||||
| import eu.siacs.conversations.utils.ExifHelper; | import eu.siacs.conversations.utils.ExifHelper; | ||||||
| import eu.siacs.conversations.utils.FileUtils; | import eu.siacs.conversations.utils.FileUtils; | ||||||
| import eu.siacs.conversations.utils.FileWriterException; | import eu.siacs.conversations.utils.FileWriterException; | ||||||
|  | import eu.siacs.conversations.utils.MimeUtils; | ||||||
| import eu.siacs.conversations.xmpp.pep.Avatar; | import eu.siacs.conversations.xmpp.pep.Avatar; | ||||||
| 
 | 
 | ||||||
| public class FileBackend { | public class FileBackend { | ||||||
| @ -276,7 +277,7 @@ public class FileBackend { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException { | 	public void copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException { | ||||||
| 		String mime = mXmppConnectionService.getContentResolver().getType(uri); | 		String mime = MimeUtils.guessMimeTypeFromUri(mXmppConnectionService, uri); | ||||||
| 		Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage (mime="+mime+")"); | 		Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage (mime="+mime+")"); | ||||||
| 		String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime); | 		String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime); | ||||||
| 		if (extension == null) { | 		if (extension == null) { | ||||||
|  | |||||||
| @ -98,6 +98,7 @@ import eu.siacs.conversations.ui.UiCallback; | |||||||
| import eu.siacs.conversations.utils.ConversationsFileObserver; | import eu.siacs.conversations.utils.ConversationsFileObserver; | ||||||
| import eu.siacs.conversations.utils.CryptoHelper; | import eu.siacs.conversations.utils.CryptoHelper; | ||||||
| import eu.siacs.conversations.utils.ExceptionHelper; | import eu.siacs.conversations.utils.ExceptionHelper; | ||||||
|  | import eu.siacs.conversations.utils.MimeUtils; | ||||||
| import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener; | import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener; | ||||||
| import eu.siacs.conversations.utils.PRNGFixes; | import eu.siacs.conversations.utils.PRNGFixes; | ||||||
| import eu.siacs.conversations.utils.PhoneHelper; | import eu.siacs.conversations.utils.PhoneHelper; | ||||||
| @ -493,9 +494,13 @@ public class XmppConnectionService extends Service { | |||||||
| 			callback.error(R.string.security_error_invalid_file_access, null); | 			callback.error(R.string.security_error_invalid_file_access, null); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		final String mimeType = MimeUtils.guessMimeTypeFromUri(this, uri); | ||||||
| 		final String compressPictures = getCompressPicturesPreference(); | 		final String compressPictures = getCompressPicturesPreference(); | ||||||
|  | 
 | ||||||
| 		if ("never".equals(compressPictures) | 		if ("never".equals(compressPictures) | ||||||
| 				|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))) { | 				|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri)) | ||||||
|  | 				|| (mimeType != null && mimeType.endsWith("/gif"))) { | ||||||
| 			Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+ ": not compressing picture. sending as file"); | 			Log.d(Config.LOGTAG,conversation.getAccount().getJid().toBareJid()+ ": not compressing picture. sending as file"); | ||||||
| 			attachFileToConversation(conversation, uri, callback); | 			attachFileToConversation(conversation, uri, callback); | ||||||
| 			return; | 			return; | ||||||
|  | |||||||
| @ -1560,6 +1560,10 @@ public class ConversationActivity extends XmppActivity | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public void attachImageToConversation(Uri uri) { | ||||||
|  | 		this.attachImageToConversation(getSelectedConversation(), uri); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	private void attachImageToConversation(Conversation conversation, Uri uri) { | 	private void attachImageToConversation(Conversation conversation, Uri uri) { | ||||||
| 		if (conversation == null) { | 		if (conversation == null) { | ||||||
| 			return; | 			return; | ||||||
|  | |||||||
| @ -11,6 +11,8 @@ import android.content.Intent; | |||||||
| import android.content.IntentSender.SendIntentException; | import android.content.IntentSender.SendIntentException; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.os.Handler; | import android.os.Handler; | ||||||
|  | import android.support.v13.view.inputmethod.InputConnectionCompat; | ||||||
|  | import android.support.v13.view.inputmethod.InputContentInfoCompat; | ||||||
| import android.text.Editable; | import android.text.Editable; | ||||||
| import android.text.InputType; | import android.text.InputType; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| @ -285,6 +287,37 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
|  | 	private EditMessage.OnCommitContentListener mEditorContentListener = new EditMessage.OnCommitContentListener() { | ||||||
|  | 		@Override | ||||||
|  | 		public boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] contentMimeTypes) { | ||||||
|  | 			// try to get permission to read the image, if applicable | ||||||
|  | 			if ((flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { | ||||||
|  | 				try { | ||||||
|  | 					inputContentInfo.requestPermission(); | ||||||
|  | 				} catch (Exception e) { | ||||||
|  | 					Log.e(Config.LOGTAG, "InputContentInfoCompat#requestPermission() failed.", e); | ||||||
|  | 					Toast.makeText( | ||||||
|  | 							activity, | ||||||
|  | 							activity.getString(R.string.no_permission_to_access_x, inputContentInfo.getDescription()), | ||||||
|  | 							Toast.LENGTH_LONG | ||||||
|  | 					).show(); | ||||||
|  | 					return false; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// send the image | ||||||
|  | 			activity.attachImageToConversation(inputContentInfo.getContentUri()); | ||||||
|  | 
 | ||||||
|  | 			// TODO: revoke permissions? | ||||||
|  | 			// since uploading an image is async its tough to wire a callback to when | ||||||
|  | 			// the image has finished uploading. | ||||||
|  | 			// According to the docs: "calling IC#releasePermission() is just to be a | ||||||
|  | 			// good citizen. Even if we failed to call that method, the system would eventually revoke | ||||||
|  | 			// the permission sometime after inputContentInfo object gets garbage-collected." | ||||||
|  | 			// See: https://developer.android.com/samples/CommitContentSampleApp/src/com.example.android.commitcontent.app/MainActivity.html#l164 | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
| 	private OnClickListener mSendButtonListener = new OnClickListener() { | 	private OnClickListener mSendButtonListener = new OnClickListener() { | ||||||
| 
 | 
 | ||||||
| 		@Override | 		@Override | ||||||
| @ -416,6 +449,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 	public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | 	public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | ||||||
| 		final View view = inflater.inflate(R.layout.fragment_conversation, container, false); | 		final View view = inflater.inflate(R.layout.fragment_conversation, container, false); | ||||||
| 		view.setOnClickListener(null); | 		view.setOnClickListener(null); | ||||||
|  | 
 | ||||||
|  | 		String[] allImagesMimeType = {"image/*"}; | ||||||
| 		mEditMessage = (EditMessage) view.findViewById(R.id.textinput); | 		mEditMessage = (EditMessage) view.findViewById(R.id.textinput); | ||||||
| 		mEditMessage.setOnClickListener(new OnClickListener() { | 		mEditMessage.setOnClickListener(new OnClickListener() { | ||||||
| 
 | 
 | ||||||
| @ -427,6 +462,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa | |||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 		mEditMessage.setOnEditorActionListener(mEditorActionListener); | 		mEditMessage.setOnEditorActionListener(mEditorActionListener); | ||||||
|  | 		mEditMessage.setRichContentListener(allImagesMimeType, mEditorContentListener); | ||||||
| 
 | 
 | ||||||
| 		mSendButton = (ImageButton) view.findViewById(R.id.textSendButton); | 		mSendButton = (ImageButton) view.findViewById(R.id.textSendButton); | ||||||
| 		mSendButton.setOnClickListener(this.mSendButtonListener); | 		mSendButton.setOnClickListener(this.mSendButtonListener); | ||||||
|  | |||||||
| @ -1,19 +1,33 @@ | |||||||
| package eu.siacs.conversations.ui; | package eu.siacs.conversations.ui; | ||||||
| 
 | 
 | ||||||
|  | import android.support.v13.view.inputmethod.EditorInfoCompat; | ||||||
|  | import android.support.v13.view.inputmethod.InputConnectionCompat; | ||||||
|  | import android.support.v13.view.inputmethod.InputContentInfoCompat; | ||||||
|  | 
 | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.os.Build; | import android.os.Build; | ||||||
|  | import android.os.Bundle; | ||||||
| import android.os.Handler; | import android.os.Handler; | ||||||
| import android.text.Editable; | import android.text.Editable; | ||||||
| import android.text.InputFilter; | import android.text.InputFilter; | ||||||
| import android.text.Spanned; | import android.text.Spanned; | ||||||
| import android.util.AttributeSet; | import android.util.AttributeSet; | ||||||
| import android.view.KeyEvent; | import android.view.KeyEvent; | ||||||
|  | import android.view.inputmethod.EditorInfo; | ||||||
|  | import android.view.inputmethod.InputConnection; | ||||||
| import android.widget.EditText; | import android.widget.EditText; | ||||||
| 
 | 
 | ||||||
| import eu.siacs.conversations.Config; | import eu.siacs.conversations.Config; | ||||||
| 
 | 
 | ||||||
| public class EditMessage extends EditText { | public class EditMessage extends EditText { | ||||||
| 
 | 
 | ||||||
|  | 	public interface OnCommitContentListener { | ||||||
|  | 		boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] mimeTypes); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private OnCommitContentListener mCommitContentListener = null; | ||||||
|  | 	private String[] mimeTypes = null; | ||||||
|  | 
 | ||||||
| 	public EditMessage(Context context, AttributeSet attrs) { | 	public EditMessage(Context context, AttributeSet attrs) { | ||||||
| 		super(context, attrs); | 		super(context, attrs); | ||||||
| 	} | 	} | ||||||
| @ -125,4 +139,27 @@ public class EditMessage extends EditText { | |||||||
| 			return super.onTextContextMenuItem(id); | 			return super.onTextContextMenuItem(id); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setRichContentListener(String[] mimeTypes, OnCommitContentListener listener) { | ||||||
|  | 		this.mimeTypes = mimeTypes; | ||||||
|  | 		this.mCommitContentListener = listener; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public InputConnection onCreateInputConnection(EditorInfo editorInfo) { | ||||||
|  | 		final InputConnection ic = super.onCreateInputConnection(editorInfo); | ||||||
|  | 
 | ||||||
|  | 		if (mimeTypes != null && mCommitContentListener != null) { | ||||||
|  | 			EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes); | ||||||
|  | 			return InputConnectionCompat.createWrapper(ic, editorInfo, new InputConnectionCompat.OnCommitContentListener() { | ||||||
|  | 				@Override | ||||||
|  | 				public boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts) { | ||||||
|  | 					return EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			return ic; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,6 +14,9 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| package eu.siacs.conversations.utils; | package eu.siacs.conversations.utils; | ||||||
|  | import android.content.Context; | ||||||
|  | import android.net.Uri; | ||||||
|  | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| @ -484,4 +487,22 @@ public final class MimeUtils { | |||||||
|         } |         } | ||||||
|         return mimeTypeToExtensionMap.get(mimeType); |         return mimeTypeToExtensionMap.get(mimeType); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public static String guessMimeTypeFromUri(Context context, Uri uri) { | ||||||
|  |         // try the content resolver | ||||||
|  |         String mimeType = context.getContentResolver().getType(uri); | ||||||
|  |         // try the extension | ||||||
|  |         if (mimeType == null && uri.getPath() != null) { | ||||||
|  |             String path = uri.getPath(); | ||||||
|  |             int start = path.lastIndexOf('.') + 1; | ||||||
|  |             if (start < path.length()) { | ||||||
|  |                 mimeType = MimeUtils.guessMimeTypeFromExtension(path.substring(start)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // sometimes this works (as with the commit content api) | ||||||
|  |         if (mimeType == null) { | ||||||
|  |             mimeType = uri.getQueryParameter("mimeType"); | ||||||
|  |         } | ||||||
|  |         return mimeType; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch