Support for sending arbitrary file types

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-04-18 16:33:03 -07:00
parent c3164a8e84
commit 2b79e131a7
12 changed files with 48 additions and 148 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

View File

@ -34,14 +34,14 @@
android:src="@drawable/ic_image_white_36dp" android:src="@drawable/ic_image_white_36dp"
android:scaleType="center" android:scaleType="center"
android:elevation="4dp" android:elevation="4dp"
android:contentDescription="@string/attachment_type_selector__image_description" android:contentDescription="@string/attachment_type_selector__gallery_description"
app:circleColor="@color/purple_400"/> app:circleColor="@color/purple_400"/>
<TextView android:layout_marginTop="10dp" <TextView android:layout_marginTop="10dp"
style="@style/AttachmentTypeLabel" style="@style/AttachmentTypeLabel"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/attachment_type_selector__image"/> android:text="@string/attachment_type_selector__gallery"/>
</LinearLayout> </LinearLayout>
@ -76,20 +76,20 @@
android:orientation="vertical"> android:orientation="vertical">
<org.thoughtcrime.securesms.components.CircleColorImageView <org.thoughtcrime.securesms.components.CircleColorImageView
android:id="@+id/video_button" android:id="@+id/document_button"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:src="@drawable/ic_local_movies_white_36dp" android:src="@drawable/ic_insert_drive_file_white_36dp"
android:scaleType="center" android:scaleType="center"
android:elevation="4dp" android:elevation="4dp"
android:contentDescription="@string/attachment_type_selector__video_description" android:contentDescription="@string/attachment_type_selector__document_description"
app:circleColor="@color/red_400"/> app:circleColor="@color/red_400"/>
<TextView android:layout_marginTop="10dp" <TextView android:layout_marginTop="10dp"
style="@style/AttachmentTypeLabel" style="@style/AttachmentTypeLabel"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/attachment_type_selector__video"/> android:text="@string/attachment_type_selector__document"/>
</LinearLayout> </LinearLayout>

View File

@ -702,12 +702,8 @@
<!-- attachment_type_selector --> <!-- attachment_type_selector -->
<string name="attachment_type_selector__image">Image</string>
<string name="attachment_type_selector__image_description">Image</string>
<string name="attachment_type_selector__audio">Audio</string> <string name="attachment_type_selector__audio">Audio</string>
<string name="attachment_type_selector__audio_description">Audio</string> <string name="attachment_type_selector__audio_description">Audio</string>
<string name="attachment_type_selector__video">Video</string>
<string name="attachment_type_selector__video_description">Video</string>
<string name="attachment_type_selector__contact">Contact</string> <string name="attachment_type_selector__contact">Contact</string>
<string name="attachment_type_selector__contact_description">Contact</string> <string name="attachment_type_selector__contact_description">Contact</string>
<string name="attachment_type_selector__camera">Camera</string> <string name="attachment_type_selector__camera">Camera</string>
@ -716,6 +712,11 @@
<string name="attachment_type_selector__location_description">Location</string> <string name="attachment_type_selector__location_description">Location</string>
<string name="attachment_type_selector__gif">GIF</string> <string name="attachment_type_selector__gif">GIF</string>
<string name="attachment_type_selector__gif_description">Gif</string> <string name="attachment_type_selector__gif_description">Gif</string>
<string name="attachment_type_selector__gallery_description">Image or video</string>
<string name="attachment_type_selector__document_description">Document</string>
<string name="attachment_type_selector__gallery">Gallery</string>
<string name="attachment_type_selector__document">Document</string>
<string name="attachment_type_selector__drawer_description">Toggle attachment drawer</string> <string name="attachment_type_selector__drawer_description">Toggle attachment drawer</string>
<!-- change_passphrase_activity --> <!-- change_passphrase_activity -->

View File

@ -106,7 +106,6 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
import org.thoughtcrime.securesms.mms.AttachmentManager; import org.thoughtcrime.securesms.mms.AttachmentManager;
import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType; import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType;
import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
import org.thoughtcrime.securesms.mms.AudioSlide; import org.thoughtcrime.securesms.mms.AudioSlide;
import org.thoughtcrime.securesms.mms.LocationSlide; import org.thoughtcrime.securesms.mms.LocationSlide;
import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.MediaConstraints;
@ -189,8 +188,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public static final String TIMING_EXTRA = "timing"; public static final String TIMING_EXTRA = "timing";
public static final String LAST_SEEN_EXTRA = "last_seen"; public static final String LAST_SEEN_EXTRA = "last_seen";
private static final int PICK_IMAGE = 1; private static final int PICK_GALLERY = 1;
private static final int PICK_VIDEO = 2; private static final int PICK_DOCUMENT = 2;
private static final int PICK_AUDIO = 3; private static final int PICK_AUDIO = 3;
private static final int PICK_CONTACT_INFO = 4; private static final int PICK_CONTACT_INFO = 4;
private static final int GROUP_EDIT = 5; private static final int GROUP_EDIT = 5;
@ -374,12 +373,19 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
switch (reqCode) { switch (reqCode) {
case PICK_IMAGE: case PICK_GALLERY:
boolean isGif = MediaUtil.isGif(MediaUtil.getMimeType(this, data.getData())); MediaType mediaType;
setMedia(data.getData(), isGif ? MediaType.GIF : MediaType.IMAGE);
String mimeType = MediaUtil.getMimeType(this, data.getData());
if (MediaUtil.isGif(mimeType)) mediaType = MediaType.GIF;
else if (MediaUtil.isVideo(mimeType)) mediaType = MediaType.VIDEO;
else mediaType = MediaType.IMAGE;
setMedia(data.getData(), mediaType);
break; break;
case PICK_VIDEO: case PICK_DOCUMENT:
setMedia(data.getData(), MediaType.VIDEO); setMedia(data.getData(), MediaType.DOCUMENT);
break; break;
case PICK_AUDIO: case PICK_AUDIO:
setMedia(data.getData(), MediaType.AUDIO); setMedia(data.getData(), MediaType.AUDIO);
@ -1198,17 +1204,17 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void addAttachment(int type) { private void addAttachment(int type) {
Log.w("ComposeMessageActivity", "Selected: " + type); Log.w("ComposeMessageActivity", "Selected: " + type);
switch (type) { switch (type) {
case AttachmentTypeSelectorAdapter.ADD_IMAGE: case AttachmentTypeSelector.ADD_GALLERY:
AttachmentManager.selectImage(this, PICK_IMAGE); break; AttachmentManager.selectGallery(this, PICK_GALLERY); break;
case AttachmentTypeSelectorAdapter.ADD_VIDEO: case AttachmentTypeSelector.ADD_DOCUMENT:
AttachmentManager.selectVideo(this, PICK_VIDEO); break; AttachmentManager.selectDocument(this, PICK_DOCUMENT); break;
case AttachmentTypeSelectorAdapter.ADD_SOUND: case AttachmentTypeSelector.ADD_SOUND:
AttachmentManager.selectAudio(this, PICK_AUDIO); break; AttachmentManager.selectAudio(this, PICK_AUDIO); break;
case AttachmentTypeSelectorAdapter.ADD_CONTACT_INFO: case AttachmentTypeSelector.ADD_CONTACT_INFO:
AttachmentManager.selectContactInfo(this, PICK_CONTACT_INFO); break; AttachmentManager.selectContactInfo(this, PICK_CONTACT_INFO); break;
case AttachmentTypeSelector.ADD_LOCATION: case AttachmentTypeSelector.ADD_LOCATION:
AttachmentManager.selectLocation(this, PICK_LOCATION); break; AttachmentManager.selectLocation(this, PICK_LOCATION); break;
case AttachmentTypeSelectorAdapter.TAKE_PHOTO: case AttachmentTypeSelector.TAKE_PHOTO:
attachmentManager.capturePhoto(this, TAKE_PHOTO); break; attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
case AttachmentTypeSelector.ADD_GIF: case AttachmentTypeSelector.ADD_GIF:
AttachmentManager.selectGif(this, PICK_GIF, !isSecureText); break; AttachmentManager.selectGif(this, PICK_GIF, !isSecureText); break;
@ -1723,7 +1729,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Intent intent = new Intent(); Intent intent = new Intent();
intent.setData(uri); intent.setData(uri);
onActivityResult(PICK_IMAGE, RESULT_OK, intent); onActivityResult(PICK_GALLERY, RESULT_OK, intent);
} }
} }

View File

@ -30,8 +30,8 @@ import org.thoughtcrime.securesms.util.ViewUtil;
public class AttachmentTypeSelector extends PopupWindow { public class AttachmentTypeSelector extends PopupWindow {
public static final int ADD_IMAGE = 1; public static final int ADD_GALLERY = 1;
public static final int ADD_VIDEO = 2; public static final int ADD_DOCUMENT = 2;
public static final int ADD_SOUND = 3; public static final int ADD_SOUND = 3;
public static final int ADD_CONTACT_INFO = 4; public static final int ADD_CONTACT_INFO = 4;
public static final int TAKE_PHOTO = 5; public static final int TAKE_PHOTO = 5;
@ -44,7 +44,7 @@ public class AttachmentTypeSelector extends PopupWindow {
private final @NonNull ImageView imageButton; private final @NonNull ImageView imageButton;
private final @NonNull ImageView audioButton; private final @NonNull ImageView audioButton;
private final @NonNull ImageView videoButton; private final @NonNull ImageView documentButton;
private final @NonNull ImageView contactButton; private final @NonNull ImageView contactButton;
private final @NonNull ImageView cameraButton; private final @NonNull ImageView cameraButton;
private final @NonNull ImageView locationButton; private final @NonNull ImageView locationButton;
@ -64,16 +64,16 @@ public class AttachmentTypeSelector extends PopupWindow {
this.listener = listener; this.listener = listener;
this.imageButton = ViewUtil.findById(layout, R.id.gallery_button); this.imageButton = ViewUtil.findById(layout, R.id.gallery_button);
this.audioButton = ViewUtil.findById(layout, R.id.audio_button); this.audioButton = ViewUtil.findById(layout, R.id.audio_button);
this.videoButton = ViewUtil.findById(layout, R.id.video_button); this.documentButton = ViewUtil.findById(layout, R.id.document_button);
this.contactButton = ViewUtil.findById(layout, R.id.contact_button); this.contactButton = ViewUtil.findById(layout, R.id.contact_button);
this.cameraButton = ViewUtil.findById(layout, R.id.camera_button); this.cameraButton = ViewUtil.findById(layout, R.id.camera_button);
this.locationButton = ViewUtil.findById(layout, R.id.location_button); this.locationButton = ViewUtil.findById(layout, R.id.location_button);
this.gifButton = ViewUtil.findById(layout, R.id.giphy_button); this.gifButton = ViewUtil.findById(layout, R.id.giphy_button);
this.closeButton = ViewUtil.findById(layout, R.id.close_button); this.closeButton = ViewUtil.findById(layout, R.id.close_button);
this.imageButton.setOnClickListener(new PropagatingClickListener(ADD_IMAGE)); this.imageButton.setOnClickListener(new PropagatingClickListener(ADD_GALLERY));
this.audioButton.setOnClickListener(new PropagatingClickListener(ADD_SOUND)); this.audioButton.setOnClickListener(new PropagatingClickListener(ADD_SOUND));
this.videoButton.setOnClickListener(new PropagatingClickListener(ADD_VIDEO)); this.documentButton.setOnClickListener(new PropagatingClickListener(ADD_DOCUMENT));
this.contactButton.setOnClickListener(new PropagatingClickListener(ADD_CONTACT_INFO)); this.contactButton.setOnClickListener(new PropagatingClickListener(ADD_CONTACT_INFO));
this.cameraButton.setOnClickListener(new PropagatingClickListener(TAKE_PHOTO)); this.cameraButton.setOnClickListener(new PropagatingClickListener(TAKE_PHOTO));
this.locationButton.setOnClickListener(new PropagatingClickListener(ADD_LOCATION)); this.locationButton.setOnClickListener(new PropagatingClickListener(ADD_LOCATION));
@ -121,7 +121,7 @@ public class AttachmentTypeSelector extends PopupWindow {
animateButtonIn(audioButton, ANIMATION_DURATION / 3); animateButtonIn(audioButton, ANIMATION_DURATION / 3);
animateButtonIn(locationButton, ANIMATION_DURATION / 3); animateButtonIn(locationButton, ANIMATION_DURATION / 3);
animateButtonIn(videoButton, ANIMATION_DURATION / 4); animateButtonIn(documentButton, ANIMATION_DURATION / 4);
animateButtonIn(gifButton, ANIMATION_DURATION / 4); animateButtonIn(gifButton, ANIMATION_DURATION / 4);
animateButtonIn(contactButton, 0); animateButtonIn(contactButton, 0);
animateButtonIn(closeButton, 0); animateButtonIn(closeButton, 0);

View File

@ -297,12 +297,12 @@ public class AttachmentManager {
return deck; return deck;
} }
public static void selectVideo(Activity activity, int requestCode) { public static void selectDocument(Activity activity, int requestCode) {
selectMediaType(activity, "video/*", requestCode); selectMediaType(activity, "*/*", requestCode);
} }
public static void selectImage(Activity activity, int requestCode) { public static void selectGallery(Activity activity, int requestCode) {
selectMediaType(activity, "image/*", requestCode); selectMediaType(activity, "image/* video/*", requestCode);
} }
public static void selectAudio(Activity activity, int requestCode) { public static void selectAudio(Activity activity, int requestCode) {

View File

@ -1,111 +0,0 @@
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ResUtil;
import java.util.ArrayList;
import java.util.List;
public class AttachmentTypeSelectorAdapter extends ArrayAdapter<AttachmentTypeSelectorAdapter.IconListItem> {
public static final int ADD_IMAGE = 1;
public static final int ADD_VIDEO = 2;
public static final int ADD_SOUND = 3;
public static final int ADD_CONTACT_INFO = 4;
public static final int TAKE_PHOTO = 5;
private final Context context;
public AttachmentTypeSelectorAdapter(Context context) {
super(context, R.layout.icon_list_item, getItemList(context));
this.context = context;
}
public int buttonToCommand(int position) {
return getItem(position).getCommand();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.icon_list_item, parent, false);
} else {
view = convertView;
}
TextView text = (TextView) view.findViewById(R.id.text1);
ImageView image = (ImageView) view.findViewById(R.id.icon);
text.setText(getItem(position).getTitle());
image.setImageResource(getItem(position).getResource());
return view;
}
private static List<IconListItem> getItemList(Context context) {
List<IconListItem> data = new ArrayList<>(4);
addItem(data, context.getString(R.string.AttachmentTypeSelectorAdapter_camera), ResUtil.getDrawableRes(context, R.attr.conversation_attach_camera), TAKE_PHOTO);
addItem(data, context.getString(R.string.AttachmentTypeSelectorAdapter_picture), ResUtil.getDrawableRes(context, R.attr.conversation_attach_image), ADD_IMAGE);
addItem(data, context.getString(R.string.AttachmentTypeSelectorAdapter_video), ResUtil.getDrawableRes(context, R.attr.conversation_attach_video), ADD_VIDEO);
addItem(data, context.getString(R.string.AttachmentTypeSelectorAdapter_audio), ResUtil.getDrawableRes(context, R.attr.conversation_attach_sound), ADD_SOUND);
addItem(data, context.getString(R.string.AttachmentTypeSelectorAdapter_contact), ResUtil.getDrawableRes(context, R.attr.conversation_attach_contact_info), ADD_CONTACT_INFO);
return data;
}
private static void addItem(List<IconListItem> list, String text, int resource, int id) {
list.add(new IconListItem(text, resource, id));
}
public static class IconListItem {
private final String title;
private final int resource;
private final int id;
public IconListItem(String title, int resource, int id) {
this.resource = resource;
this.title = title;
this.id = id;
}
public int getCommand() {
return id;
}
public String getTitle() {
return title;
}
public int getResource() {
return resource;
}
}
}

View File

@ -158,6 +158,10 @@ public class MediaUtil {
return ContentType.isVideoType(attachment.getContentType()); return ContentType.isVideoType(attachment.getContentType());
} }
public static boolean isVideo(String contentType) {
return !TextUtils.isEmpty(contentType) && contentType.trim().startsWith("video/");
}
public static @Nullable String getDiscreteMimeType(@NonNull String mimeType) { public static @Nullable String getDiscreteMimeType(@NonNull String mimeType) {
final String[] sections = mimeType.split("/", 2); final String[] sections = mimeType.split("/", 2);
return sections.length > 1 ? sections[0] : null; return sections.length > 1 ? sections[0] : null;