mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-24 23:09:02 +03:00
Add Exif orientation info to ContentAttachmentData
This commit is contained in:
parent
53572a3be6
commit
f34f28b668
6 changed files with 96 additions and 1 deletions
matrix-sdk-android
build.gradle
src/main/java/im/vector/matrix/android
vector/src/main/java/im/vector/riotx
|
@ -118,6 +118,9 @@ dependencies {
|
||||||
|
|
||||||
implementation "ru.noties.markwon:core:$markwon_version"
|
implementation "ru.noties.markwon:core:$markwon_version"
|
||||||
|
|
||||||
|
// Image
|
||||||
|
implementation 'androidx.exifinterface:exifinterface:1.0.0'
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
|
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
|
||||||
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.matrix.android.api.session.content
|
package im.vector.matrix.android.api.session.content
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
@ -26,6 +27,7 @@ data class ContentAttachmentData(
|
||||||
val date: Long = 0,
|
val date: Long = 0,
|
||||||
val height: Long? = 0,
|
val height: Long? = 0,
|
||||||
val width: Long? = 0,
|
val width: Long? = 0,
|
||||||
|
val exifOrientation: Int = ExifInterface.ORIENTATION_UNDEFINED,
|
||||||
val name: String? = null,
|
val name: String? = null,
|
||||||
val path: String,
|
val path: String,
|
||||||
val mimeType: String,
|
val mimeType: String,
|
||||||
|
|
|
@ -180,6 +180,7 @@ internal class LocalEchoEventFactory @Inject constructor(@UserId private val use
|
||||||
mimeType = attachment.mimeType,
|
mimeType = attachment.mimeType,
|
||||||
width = attachment.width?.toInt() ?: 0,
|
width = attachment.width?.toInt() ?: 0,
|
||||||
height = attachment.height?.toInt() ?: 0,
|
height = attachment.height?.toInt() ?: 0,
|
||||||
|
orientation = attachment.exifOrientation,
|
||||||
size = attachment.size.toInt()
|
size = attachment.size.toInt()
|
||||||
),
|
),
|
||||||
url = attachment.path
|
url = attachment.path
|
||||||
|
|
|
@ -26,6 +26,7 @@ import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.riotx.EmojiCompatFontProvider
|
import im.vector.riotx.EmojiCompatFontProvider
|
||||||
import im.vector.riotx.EmojiCompatWrapper
|
import im.vector.riotx.EmojiCompatWrapper
|
||||||
import im.vector.riotx.VectorApplication
|
import im.vector.riotx.VectorApplication
|
||||||
|
import im.vector.riotx.core.images.ImageTools
|
||||||
import im.vector.riotx.core.pushers.PushersManager
|
import im.vector.riotx.core.pushers.PushersManager
|
||||||
import im.vector.riotx.core.utils.DimensionConverter
|
import im.vector.riotx.core.utils.DimensionConverter
|
||||||
import im.vector.riotx.features.configuration.VectorConfiguration
|
import im.vector.riotx.features.configuration.VectorConfiguration
|
||||||
|
@ -66,6 +67,8 @@ interface VectorComponent {
|
||||||
|
|
||||||
fun dimensionConverter(): DimensionConverter
|
fun dimensionConverter(): DimensionConverter
|
||||||
|
|
||||||
|
fun imageTools(): ImageTools
|
||||||
|
|
||||||
fun vectorConfiguration(): VectorConfiguration
|
fun vectorConfiguration(): VectorConfiguration
|
||||||
|
|
||||||
fun avatarRenderer(): AvatarRenderer
|
fun avatarRenderer(): AvatarRenderer
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* 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 im.vector.riotx.core.images
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.MediaStore
|
||||||
|
import androidx.exifinterface.media.ExifInterface
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ImageTools @Inject constructor(private val context: Context) {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the [ExifInterface] value for the orientation for this local bitmap Uri.
|
||||||
|
*
|
||||||
|
* @param uri The URI to find the orientation for. Must be local.
|
||||||
|
* @return The orientation value, which may be [ExifInterface.ORIENTATION_UNDEFINED].
|
||||||
|
*/
|
||||||
|
fun getOrientationForBitmap(uri: Uri): Int {
|
||||||
|
var orientation = ExifInterface.ORIENTATION_UNDEFINED
|
||||||
|
|
||||||
|
if (uri.scheme == "content") {
|
||||||
|
val proj = arrayOf(MediaStore.Images.Media.DATA)
|
||||||
|
var cursor: Cursor? = null
|
||||||
|
try {
|
||||||
|
cursor = context.contentResolver.query(uri, proj, null, null, null)
|
||||||
|
if (cursor != null && cursor.count > 0) {
|
||||||
|
cursor.moveToFirst()
|
||||||
|
val idxData = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
|
||||||
|
val path = cursor.getString(idxData)
|
||||||
|
if (path.isNullOrBlank()) {
|
||||||
|
Timber.w("Cannot find path in media db for uri $uri")
|
||||||
|
return orientation
|
||||||
|
}
|
||||||
|
val exif = ExifInterface(path)
|
||||||
|
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// eg SecurityException from com.google.android.apps.photos.content.GooglePhotosImageProvider URIs
|
||||||
|
// eg IOException from trying to parse the returned path as a file when it is an http uri.
|
||||||
|
Timber.e(e, "Cannot get orientation for bitmap")
|
||||||
|
} finally {
|
||||||
|
cursor?.close()
|
||||||
|
}
|
||||||
|
} else if (uri.scheme == "file") {
|
||||||
|
try {
|
||||||
|
val exif = ExifInterface(uri.path)
|
||||||
|
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "Cannot get EXIF for file uri $uri")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return orientation
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,6 +54,7 @@ import im.vector.matrix.rx.unwrap
|
||||||
import im.vector.riotx.BuildConfig
|
import im.vector.riotx.BuildConfig
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.postLiveEvent
|
import im.vector.riotx.core.extensions.postLiveEvent
|
||||||
|
import im.vector.riotx.core.images.ImageTools
|
||||||
import im.vector.riotx.core.intent.getFilenameFromUri
|
import im.vector.riotx.core.intent.getFilenameFromUri
|
||||||
import im.vector.riotx.core.platform.VectorViewModel
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
import im.vector.riotx.core.resources.UserPreferencesProvider
|
import im.vector.riotx.core.resources.UserPreferencesProvider
|
||||||
|
@ -76,6 +77,7 @@ import java.util.concurrent.TimeUnit
|
||||||
class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
|
class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
|
||||||
private val userPreferencesProvider: UserPreferencesProvider,
|
private val userPreferencesProvider: UserPreferencesProvider,
|
||||||
private val vectorPreferences: VectorPreferences,
|
private val vectorPreferences: VectorPreferences,
|
||||||
|
private val imageTools: ImageTools,
|
||||||
private val session: Session
|
private val session: Session
|
||||||
) : VectorViewModel<RoomDetailViewState>(initialState) {
|
) : VectorViewModel<RoomDetailViewState>(initialState) {
|
||||||
|
|
||||||
|
@ -470,7 +472,14 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
|
|
||||||
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
|
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
|
||||||
val attachments = action.mediaFiles.map {
|
val attachments = action.mediaFiles.map {
|
||||||
val nameWithExtension = getFilenameFromUri(null, Uri.parse(it.path))
|
val pathWithScheme = if (it.path.startsWith("/")) {
|
||||||
|
"file://" + it.path
|
||||||
|
} else {
|
||||||
|
it.path
|
||||||
|
}
|
||||||
|
|
||||||
|
val uri = Uri.parse(pathWithScheme)
|
||||||
|
val nameWithExtension = getFilenameFromUri(null, uri)
|
||||||
|
|
||||||
ContentAttachmentData(
|
ContentAttachmentData(
|
||||||
size = it.size,
|
size = it.size,
|
||||||
|
@ -478,6 +487,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
date = it.date,
|
date = it.date,
|
||||||
height = it.height,
|
height = it.height,
|
||||||
width = it.width,
|
width = it.width,
|
||||||
|
exifOrientation = imageTools.getOrientationForBitmap(uri),
|
||||||
name = nameWithExtension ?: it.name,
|
name = nameWithExtension ?: it.name,
|
||||||
path = it.path,
|
path = it.path,
|
||||||
mimeType = it.mimeType,
|
mimeType = it.mimeType,
|
||||||
|
|
Loading…
Add table
Reference in a new issue