~singpolyma/cheogram-android

5a670c88b081d3f9b8d33e37fd8d966f04c245fc — Michael Eden 6 years ago 8c34bb3
Do not compress GIFs, allow GBoard to send GIFs
M build.gradle => build.gradle +1 -1
@@ 26,7 26,7 @@ dependencies {
    playstoreCompile 'com.google.android.gms:play-services-gcm:9.4.0'
    compile 'org.sufficientlysecure:openpgp-api:10.0'
    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:bcmail-jdk15on:1.52'
    compile 'org.jitsi:org.otr4j:0.22'

M src/main/java/eu/siacs/conversations/persistance/FileBackend.java => src/main/java/eu/siacs/conversations/persistance/FileBackend.java +2 -1
@@ 55,6 55,7 @@ import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.ExifHelper;
import eu.siacs.conversations.utils.FileUtils;
import eu.siacs.conversations.utils.FileWriterException;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.xmpp.pep.Avatar;

public class FileBackend {


@@ 276,7 277,7 @@ public class FileBackend {
	}

	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+")");
		String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
		if (extension == null) {

M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java => src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +6 -1
@@ 98,6 98,7 @@ import eu.siacs.conversations.ui.UiCallback;
import eu.siacs.conversations.utils.ConversationsFileObserver;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.MimeUtils;
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
import eu.siacs.conversations.utils.PRNGFixes;
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);
			return;
		}

		final String mimeType = MimeUtils.guessMimeTypeFromUri(this, uri);
		final String compressPictures = getCompressPicturesPreference();

		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");
			attachFileToConversation(conversation, uri, callback);
			return;

M src/main/java/eu/siacs/conversations/ui/ConversationActivity.java => src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +4 -0
@@ 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) {
		if (conversation == null) {
			return;

M src/main/java/eu/siacs/conversations/ui/ConversationFragment.java => src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +36 -0
@@ 11,6 11,8 @@ import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
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.InputType;
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() {

		@Override


@@ 416,6 449,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
	public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		final View view = inflater.inflate(R.layout.fragment_conversation, container, false);
		view.setOnClickListener(null);

		String[] allImagesMimeType = {"image/*"};
		mEditMessage = (EditMessage) view.findViewById(R.id.textinput);
		mEditMessage.setOnClickListener(new OnClickListener() {



@@ 427,6 462,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
			}
		});
		mEditMessage.setOnEditorActionListener(mEditorActionListener);
		mEditMessage.setRichContentListener(allImagesMimeType, mEditorContentListener);

		mSendButton = (ImageButton) view.findViewById(R.id.textSendButton);
		mSendButton.setOnClickListener(this.mSendButtonListener);

M src/main/java/eu/siacs/conversations/ui/EditMessage.java => src/main/java/eu/siacs/conversations/ui/EditMessage.java +37 -0
@@ 1,19 1,33 @@
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.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Spanned;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;

import eu.siacs.conversations.Config;

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) {
		super(context, attrs);
	}


@@ 125,4 139,27 @@ public class EditMessage extends EditText {
			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;
		}
	}
}

M src/main/java/eu/siacs/conversations/utils/MimeUtils.java => src/main/java/eu/siacs/conversations/utils/MimeUtils.java +21 -0
@@ 14,6 14,9 @@
 * limitations under the License.
 */
package eu.siacs.conversations.utils;
import android.content.Context;
import android.net.Uri;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


@@ 484,4 487,22 @@ public final class MimeUtils {
        }
        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;
    }
}