mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 16:49:40 +01:00
Ensure images sent to stories respect media quality settings.
Stories should always use "Standard" quality, not L3 (high quality). This change ensures that we: 1. Always send stories at the appropriate quality 2. Do not corrupt or overwrite pre-existing image attachments 3. Close several streams when done (thanks StrictMode!)
This commit is contained in:
committed by
Cody Henthorne
parent
c4bef8099f
commit
b18542a839
@@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.components.ThumbnailView;
|
||||
import org.thoughtcrime.securesms.components.location.SignalMapView;
|
||||
import org.thoughtcrime.securesms.components.location.SignalPlace;
|
||||
import org.thoughtcrime.securesms.conversation.MessageSendType;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.giph.ui.GiphyActivity;
|
||||
import org.thoughtcrime.securesms.maps.PlacePickerActivity;
|
||||
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity;
|
||||
@@ -316,7 +317,7 @@ public class AttachmentManager {
|
||||
}
|
||||
|
||||
Log.d(TAG, "remote slide with size " + fileSize + " took " + (System.currentTimeMillis() - start) + "ms");
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, fileSize, width, height, false);
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, fileSize, width, height, false, null);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
@@ -326,17 +327,19 @@ public class AttachmentManager {
|
||||
}
|
||||
|
||||
private @NonNull Slide getManuallyCalculatedSlideInfo(Uri uri, int width, int height) throws IOException {
|
||||
long start = System.currentTimeMillis();
|
||||
Long mediaSize = null;
|
||||
String fileName = null;
|
||||
String mimeType = null;
|
||||
boolean gif = false;
|
||||
long start = System.currentTimeMillis();
|
||||
Long mediaSize = null;
|
||||
String fileName = null;
|
||||
String mimeType = null;
|
||||
boolean gif = false;
|
||||
AttachmentDatabase.TransformProperties transformProperties = null;
|
||||
|
||||
if (PartAuthority.isLocalUri(uri)) {
|
||||
mediaSize = PartAuthority.getAttachmentSize(context, uri);
|
||||
fileName = PartAuthority.getAttachmentFileName(context, uri);
|
||||
mimeType = PartAuthority.getAttachmentContentType(context, uri);
|
||||
gif = PartAuthority.getAttachmentIsVideoGif(context, uri);
|
||||
mediaSize = PartAuthority.getAttachmentSize(context, uri);
|
||||
fileName = PartAuthority.getAttachmentFileName(context, uri);
|
||||
mimeType = PartAuthority.getAttachmentContentType(context, uri);
|
||||
gif = PartAuthority.getAttachmentIsVideoGif(context, uri);
|
||||
transformProperties = PartAuthority.getAttachmentTransformProperties(uri);
|
||||
}
|
||||
|
||||
if (mediaSize == null) {
|
||||
@@ -354,7 +357,7 @@ public class AttachmentManager {
|
||||
}
|
||||
|
||||
Log.d(TAG, "local slide with size " + mediaSize + " took " + (System.currentTimeMillis() - start) + "ms");
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, mediaSize, width, height, gif);
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, mediaSize, width, height, gif, transformProperties);
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ public abstract class MediaConstraints {
|
||||
public abstract int getImageMaxHeight(Context context);
|
||||
public abstract int getImageMaxSize(Context context);
|
||||
|
||||
public boolean isHighQuality() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a list of dimensions that should be attempted during compression. We will keep moving
|
||||
* down the list until the image can be scaled to fit under {@link #getImageMaxSize(Context)}.
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId;
|
||||
import org.thoughtcrime.securesms.avatar.AvatarPickerStorage;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiFiles;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
@@ -152,6 +153,16 @@ public class PartAuthority {
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable AttachmentDatabase.TransformProperties getAttachmentTransformProperties(@NonNull Uri uri) {
|
||||
int match = uriMatcher.match(uri);
|
||||
switch (match) {
|
||||
case PART_ROW:
|
||||
return SignalDatabase.attachments().getTransformProperties(new PartUriParser(uri).getPartId());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Uri getAttachmentPublicUri(Uri uri) {
|
||||
PartUriParser partUri = new PartUriParser(uri);
|
||||
return PartProvider.getContentUri(partUri.getPartId());
|
||||
|
||||
@@ -23,6 +23,11 @@ public class PushMediaConstraints extends MediaConstraints {
|
||||
currentConfig = getCurrentConfig(ApplicationDependencies.getApplication(), sentMediaQuality);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHighQuality() {
|
||||
return currentConfig == MediaConfig.LEVEL_3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageMaxWidth(Context context) {
|
||||
return currentConfig.imageSizeTargets[0];
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.annotation.WorkerThread;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.blurhash.BlurHash;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -31,25 +32,25 @@ public final class SlideFactory {
|
||||
/**
|
||||
* Generates a slide from the given parameters.
|
||||
*
|
||||
* @param context Application context
|
||||
* @param contentType The contentType of the given Uri
|
||||
* @param uri The Uri pointing to the resource to create a slide out of
|
||||
* @param width (Optional) width, can be 0.
|
||||
* @param height (Optional) height, can be 0.
|
||||
* @param context Application context
|
||||
* @param contentType The contentType of the given Uri
|
||||
* @param uri The Uri pointing to the resource to create a slide out of
|
||||
* @param width (Optional) width, can be 0.
|
||||
* @param height (Optional) height, can be 0.
|
||||
* @param transformProperties (Optional) transformProperties, can be 0.
|
||||
*
|
||||
* @return A Slide with all the information we can gather about it.
|
||||
*/
|
||||
@WorkerThread
|
||||
public static @Nullable Slide getSlide(@NonNull Context context, @Nullable String contentType, @NonNull Uri uri, int width, int height) {
|
||||
public static @Nullable Slide getSlide(@NonNull Context context, @Nullable String contentType, @NonNull Uri uri, int width, int height, @Nullable AttachmentDatabase.TransformProperties transformProperties) {
|
||||
MediaType mediaType = MediaType.from(contentType);
|
||||
|
||||
try {
|
||||
if (PartAuthority.isLocalUri(uri)) {
|
||||
return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height);
|
||||
return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height, transformProperties);
|
||||
} else {
|
||||
Slide result = getContentResolverSlideInfo(context, mediaType, uri, width, height);
|
||||
Slide result = getContentResolverSlideInfo(context, mediaType, uri, width, height, transformProperties);
|
||||
|
||||
if (result == null) return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height);
|
||||
if (result == null) return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height, transformProperties);
|
||||
else return result;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -58,7 +59,14 @@ public final class SlideFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Slide getContentResolverSlideInfo(@NonNull Context context, @Nullable MediaType mediaType, @NonNull Uri uri, int width, int height) {
|
||||
private static @Nullable Slide getContentResolverSlideInfo(
|
||||
@NonNull Context context,
|
||||
@Nullable MediaType mediaType,
|
||||
@NonNull Uri uri,
|
||||
int width,
|
||||
int height,
|
||||
@Nullable AttachmentDatabase.TransformProperties transformProperties
|
||||
) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
|
||||
@@ -78,14 +86,22 @@ public final class SlideFactory {
|
||||
}
|
||||
|
||||
Log.d(TAG, "remote slide with size " + fileSize + " took " + (System.currentTimeMillis() - start) + "ms");
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, fileSize, width, height, false);
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, fileSize, width, height, false, transformProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static @NonNull Slide getManuallyCalculatedSlideInfo(@NonNull Context context, @Nullable MediaType mediaType, @NonNull Uri uri, int width, int height) throws IOException {
|
||||
private static @NonNull Slide getManuallyCalculatedSlideInfo(
|
||||
@NonNull Context context,
|
||||
@Nullable MediaType mediaType,
|
||||
@NonNull Uri uri,
|
||||
int width,
|
||||
int height,
|
||||
@Nullable AttachmentDatabase.TransformProperties transformProperties
|
||||
) throws IOException
|
||||
{
|
||||
long start = System.currentTimeMillis();
|
||||
Long mediaSize = null;
|
||||
String fileName = null;
|
||||
@@ -118,7 +134,7 @@ public final class SlideFactory {
|
||||
}
|
||||
|
||||
Log.d(TAG, "local slide with size " + mediaSize + " took " + (System.currentTimeMillis() - start) + "ms");
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, mediaSize, width, height, gif);
|
||||
return mediaType.createSlide(context, uri, fileName, mimeType, null, mediaSize, width, height, gif, transformProperties);
|
||||
}
|
||||
|
||||
public enum MediaType {
|
||||
@@ -142,17 +158,18 @@ public final class SlideFactory {
|
||||
@Nullable String fileName,
|
||||
@Nullable String mimeType,
|
||||
@Nullable BlurHash blurHash,
|
||||
long dataSize,
|
||||
int width,
|
||||
int height,
|
||||
boolean gif)
|
||||
long dataSize,
|
||||
int width,
|
||||
int height,
|
||||
boolean gif,
|
||||
@Nullable AttachmentDatabase.TransformProperties transformProperties)
|
||||
{
|
||||
if (mimeType == null) {
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
|
||||
switch (this) {
|
||||
case IMAGE: return new ImageSlide(context, uri, dataSize, width, height, blurHash);
|
||||
case IMAGE: return new ImageSlide(context, uri, mimeType, dataSize, width, height, false, null, blurHash, transformProperties);
|
||||
case GIF: return new GifSlide(context, uri, dataSize, width, height);
|
||||
case AUDIO: return new AudioSlide(context, uri, dataSize, false);
|
||||
case VIDEO: return new VideoSlide(context, uri, dataSize, gif);
|
||||
|
||||
Reference in New Issue
Block a user