Use "image/jpeg" instead of "image/jpg"
This commit is contained in:
parent
26d387cc12
commit
d4384328fe
|
@ -5,11 +5,12 @@ Features ✨:
|
||||||
-
|
-
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
-
|
- Share image and other media from e2e rooms (#677)
|
||||||
|
|
||||||
Bugfix 🐛:
|
Bugfix 🐛:
|
||||||
- Fix crash on attachment preview screen (#1088)
|
- Fix crash on attachment preview screen (#1088)
|
||||||
- "Share" option is not appearing in encrypted rooms for images (#1031)
|
- "Share" option is not appearing in encrypted rooms for images (#1031)
|
||||||
|
- Set "image/jpeg" as MIME type of images instead of "image/jpg" (#1075)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
|
@ -41,4 +41,6 @@ data class ContentAttachmentData(
|
||||||
AUDIO,
|
AUDIO,
|
||||||
VIDEO
|
VIDEO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSafeMimeType() = if (mimeType == "image/jpg") "image/jpeg" else mimeType
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,4 +51,4 @@ data class MessageAudioContent(
|
||||||
* Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
|
* Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
|
||||||
*/
|
*/
|
||||||
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
||||||
) : MessageEncryptedContent
|
) : MessageWithAttachmentContent
|
||||||
|
|
|
@ -57,7 +57,7 @@ data class MessageFileContent(
|
||||||
* Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
|
* Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
|
||||||
*/
|
*/
|
||||||
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
||||||
) : MessageEncryptedContent {
|
) : MessageWithAttachmentContent {
|
||||||
|
|
||||||
fun getMimeType(): String {
|
fun getMimeType(): String {
|
||||||
// Mimetype default to plain text, should not be used
|
// Mimetype default to plain text, should not be used
|
||||||
|
|
|
@ -20,6 +20,6 @@ package im.vector.matrix.android.api.session.room.model.message
|
||||||
/**
|
/**
|
||||||
* A content with image information
|
* A content with image information
|
||||||
*/
|
*/
|
||||||
interface MessageImageInfoContent : MessageEncryptedContent {
|
interface MessageImageInfoContent : MessageWithAttachmentContent {
|
||||||
val info: ImageInfo?
|
val info: ImageInfo?
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,4 +51,4 @@ data class MessageVideoContent(
|
||||||
* Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
|
* Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
|
||||||
*/
|
*/
|
||||||
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
||||||
) : MessageEncryptedContent
|
) : MessageWithAttachmentContent
|
||||||
|
|
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo
|
||||||
/**
|
/**
|
||||||
* Interface for message which can contains an encrypted file
|
* Interface for message which can contains an encrypted file
|
||||||
*/
|
*/
|
||||||
interface MessageEncryptedContent : MessageContent {
|
interface MessageWithAttachmentContent : MessageContent {
|
||||||
/**
|
/**
|
||||||
* Required if the file is unencrypted. The URL (typically MXC URI) to the image.
|
* Required if the file is unencrypted. The URL (typically MXC URI) to the image.
|
||||||
*/
|
*/
|
||||||
|
@ -36,4 +36,4 @@ interface MessageEncryptedContent : MessageContent {
|
||||||
/**
|
/**
|
||||||
* Get the url of the encrypted file or of the file
|
* Get the url of the encrypted file or of the file
|
||||||
*/
|
*/
|
||||||
fun MessageEncryptedContent.getFileUrl() = encryptedFileInfo?.url ?: url
|
fun MessageWithAttachmentContent.getFileUrl() = encryptedFileInfo?.url ?: url
|
|
@ -25,3 +25,7 @@ annotation class SessionFilesDirectory
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class SessionCacheDirectory
|
annotation class SessionCacheDirectory
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class CacheDirectory
|
||||||
|
|
|
@ -32,6 +32,7 @@ import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.matrix.olm.OlmManager
|
import org.matrix.olm.OlmManager
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
@Component(modules = [MatrixModule::class, NetworkModule::class, AuthModule::class])
|
@Component(modules = [MatrixModule::class, NetworkModule::class, AuthModule::class])
|
||||||
@MatrixScope
|
@MatrixScope
|
||||||
|
@ -52,6 +53,9 @@ internal interface MatrixComponent {
|
||||||
|
|
||||||
fun resources(): Resources
|
fun resources(): Resources
|
||||||
|
|
||||||
|
@CacheDirectory
|
||||||
|
fun cacheDir(): File
|
||||||
|
|
||||||
fun olmManager(): OlmManager
|
fun olmManager(): OlmManager
|
||||||
|
|
||||||
fun taskExecutor(): TaskExecutor
|
fun taskExecutor(): TaskExecutor
|
||||||
|
|
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.android.asCoroutineDispatcher
|
import kotlinx.coroutines.android.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import org.matrix.olm.OlmManager
|
import org.matrix.olm.OlmManager
|
||||||
|
import java.io.File
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -49,6 +50,13 @@ internal object MatrixModule {
|
||||||
return context.resources
|
return context.resources
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Provides
|
||||||
|
@CacheDirectory
|
||||||
|
fun providesCacheDir(context: Context): File {
|
||||||
|
return context.cacheDir
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Provides
|
@Provides
|
||||||
@MatrixScope
|
@MatrixScope
|
||||||
|
|
|
@ -25,6 +25,7 @@ import im.vector.matrix.android.api.session.file.FileService
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
|
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
|
||||||
|
import im.vector.matrix.android.internal.di.CacheDirectory
|
||||||
import im.vector.matrix.android.internal.di.SessionCacheDirectory
|
import im.vector.matrix.android.internal.di.SessionCacheDirectory
|
||||||
import im.vector.matrix.android.internal.di.Unauthenticated
|
import im.vector.matrix.android.internal.di.Unauthenticated
|
||||||
import im.vector.matrix.android.internal.extensions.foldToCallback
|
import im.vector.matrix.android.internal.extensions.foldToCallback
|
||||||
|
@ -43,8 +44,10 @@ import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultFileService @Inject constructor(
|
internal class DefaultFileService @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
@SessionCacheDirectory
|
@CacheDirectory
|
||||||
private val cacheDirectory: File,
|
private val cacheDirectory: File,
|
||||||
|
@SessionCacheDirectory
|
||||||
|
private val sessionCacheDirectory: File,
|
||||||
private val contentUrlResolver: ContentUrlResolver,
|
private val contentUrlResolver: ContentUrlResolver,
|
||||||
@Unauthenticated
|
@Unauthenticated
|
||||||
private val okHttpClient: OkHttpClient,
|
private val okHttpClient: OkHttpClient,
|
||||||
|
@ -63,7 +66,7 @@ internal class DefaultFileService @Inject constructor(
|
||||||
return GlobalScope.launch(coroutineDispatchers.main) {
|
return GlobalScope.launch(coroutineDispatchers.main) {
|
||||||
withContext(coroutineDispatchers.io) {
|
withContext(coroutineDispatchers.io) {
|
||||||
Try {
|
Try {
|
||||||
val folder = File(cacheDirectory, "MF")
|
val folder = File(sessionCacheDirectory, "MF")
|
||||||
if (!folder.exists()) {
|
if (!folder.exists()) {
|
||||||
folder.mkdirs()
|
folder.mkdirs()
|
||||||
}
|
}
|
||||||
|
@ -102,7 +105,7 @@ internal class DefaultFileService @Inject constructor(
|
||||||
private fun copyFile(file: File, downloadMode: FileService.DownloadMode): File {
|
private fun copyFile(file: File, downloadMode: FileService.DownloadMode): File {
|
||||||
return when (downloadMode) {
|
return when (downloadMode) {
|
||||||
FileService.DownloadMode.TO_EXPORT -> file.copyTo(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), file.name), true)
|
FileService.DownloadMode.TO_EXPORT -> file.copyTo(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), file.name), true)
|
||||||
FileService.DownloadMode.FOR_EXTERNAL_SHARE -> file.copyTo(File(File(context.cacheDir, "ext_share"), file.name), true)
|
FileService.DownloadMode.FOR_EXTERNAL_SHARE -> file.copyTo(File(File(cacheDirectory, "ext_share"), file.name), true)
|
||||||
FileService.DownloadMode.FOR_INTERNAL_USE -> file
|
FileService.DownloadMode.FOR_INTERNAL_USE -> file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,14 +178,14 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
|
||||||
Timber.v("Encrypt file")
|
Timber.v("Encrypt file")
|
||||||
notifyTracker(params) { contentUploadStateTracker.setEncrypting(it) }
|
notifyTracker(params) { contentUploadStateTracker.setEncrypting(it) }
|
||||||
|
|
||||||
val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.mimeType)
|
val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.getSafeMimeType())
|
||||||
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
|
||||||
|
|
||||||
fileUploader
|
fileUploader
|
||||||
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
|
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
|
||||||
} else {
|
} else {
|
||||||
fileUploader
|
fileUploader
|
||||||
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
|
.uploadFile(attachmentFile, attachment.name, attachment.getSafeMimeType(), progressListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSuccess(params,
|
handleSuccess(params,
|
||||||
|
|
|
@ -261,7 +261,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
msgType = MessageType.MSGTYPE_IMAGE,
|
msgType = MessageType.MSGTYPE_IMAGE,
|
||||||
body = attachment.name ?: "image",
|
body = attachment.name ?: "image",
|
||||||
info = ImageInfo(
|
info = ImageInfo(
|
||||||
mimeType = attachment.mimeType,
|
mimeType = attachment.getSafeMimeType(),
|
||||||
width = width?.toInt() ?: 0,
|
width = width?.toInt() ?: 0,
|
||||||
height = height?.toInt() ?: 0,
|
height = height?.toInt() ?: 0,
|
||||||
size = attachment.size.toInt()
|
size = attachment.size.toInt()
|
||||||
|
@ -293,7 +293,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
msgType = MessageType.MSGTYPE_VIDEO,
|
msgType = MessageType.MSGTYPE_VIDEO,
|
||||||
body = attachment.name ?: "video",
|
body = attachment.name ?: "video",
|
||||||
videoInfo = VideoInfo(
|
videoInfo = VideoInfo(
|
||||||
mimeType = attachment.mimeType,
|
mimeType = attachment.getSafeMimeType(),
|
||||||
width = width,
|
width = width,
|
||||||
height = height,
|
height = height,
|
||||||
size = attachment.size,
|
size = attachment.size,
|
||||||
|
@ -312,7 +312,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
msgType = MessageType.MSGTYPE_AUDIO,
|
msgType = MessageType.MSGTYPE_AUDIO,
|
||||||
body = attachment.name ?: "audio",
|
body = attachment.name ?: "audio",
|
||||||
audioInfo = AudioInfo(
|
audioInfo = AudioInfo(
|
||||||
mimeType = attachment.mimeType?.takeIf { it.isNotBlank() } ?: "audio/mpeg",
|
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() } ?: "audio/mpeg",
|
||||||
size = attachment.size
|
size = attachment.size
|
||||||
),
|
),
|
||||||
url = attachment.path
|
url = attachment.path
|
||||||
|
@ -325,7 +325,7 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
msgType = MessageType.MSGTYPE_FILE,
|
msgType = MessageType.MSGTYPE_FILE,
|
||||||
body = attachment.name ?: "file",
|
body = attachment.name ?: "file",
|
||||||
info = FileInfo(
|
info = FileInfo(
|
||||||
mimeType = attachment.mimeType?.takeIf { it.isNotBlank() }
|
mimeType = attachment.getSafeMimeType()?.takeIf { it.isNotBlank() }
|
||||||
?: "application/octet-stream",
|
?: "application/octet-stream",
|
||||||
size = attachment.size
|
size = attachment.size
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,6 @@ import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||||
*/
|
*/
|
||||||
fun ContentAttachmentData.isEditable(): Boolean {
|
fun ContentAttachmentData.isEditable(): Boolean {
|
||||||
return type == ContentAttachmentData.Type.IMAGE
|
return type == ContentAttachmentData.Type.IMAGE
|
||||||
&& mimeType?.startsWith("image/") == true
|
&& getSafeMimeType()?.startsWith("image/") == true
|
||||||
&& mimeType != "image/gif"
|
&& getSafeMimeType() != "image/gif"
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ package im.vector.riotx.features.home.room.detail.timeline.action
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageEncryptedContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.platform.VectorSharedAction
|
import im.vector.riotx.core.platform.VectorSharedAction
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||||
|
@ -47,7 +47,7 @@ sealed class EventSharedAction(@StringRes val titleRes: Int,
|
||||||
data class Reply(val eventId: String) :
|
data class Reply(val eventId: String) :
|
||||||
EventSharedAction(R.string.reply, R.drawable.ic_reply)
|
EventSharedAction(R.string.reply, R.drawable.ic_reply)
|
||||||
|
|
||||||
data class Share(val eventId: String, val messageContent: MessageEncryptedContent) :
|
data class Share(val eventId: String, val messageContent: MessageWithAttachmentContent) :
|
||||||
EventSharedAction(R.string.share, R.drawable.ic_share)
|
EventSharedAction(R.string.share, R.drawable.ic_share)
|
||||||
|
|
||||||
data class Resend(val eventId: String) :
|
data class Resend(val eventId: String) :
|
||||||
|
|
|
@ -29,7 +29,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.isTextMessage
|
import im.vector.matrix.android.api.session.events.model.isTextMessage
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageEncryptedContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageFormat
|
import im.vector.matrix.android.api.session.room.model.message.MessageFormat
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
|
@ -261,7 +261,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canShare(msgType)) {
|
if (canShare(msgType)) {
|
||||||
if (messageContent is MessageEncryptedContent) {
|
if (messageContent is MessageWithAttachmentContent) {
|
||||||
add(EventSharedAction.Share(timelineEvent.eventId, messageContent))
|
add(EventSharedAction.Share(timelineEvent.eventId, messageContent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue