Browse Source

Extract MxcTools and add test.

pull/1992/head
Benoit Marty 9 months ago committed by Benoit Marty
parent
commit
419a162f77
  1. 25
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessageMediaRepo.kt
  2. 2
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessageMediaRepoTest.kt
  3. 42
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt
  4. 39
      libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt
  5. 25
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationMediaRepo.kt

25
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessageMediaRepo.kt

@ -24,6 +24,7 @@ import io.element.android.libraries.di.CacheDirectory
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.mxc.MxcTools
import java.io.File import java.io.File
/** /**
@ -66,6 +67,7 @@ interface VoiceMessageMediaRepo {
class DefaultVoiceMessageMediaRepo @AssistedInject constructor( class DefaultVoiceMessageMediaRepo @AssistedInject constructor(
@CacheDirectory private val cacheDir: File, @CacheDirectory private val cacheDir: File,
mxcTools: MxcTools,
private val matrixMediaLoader: MatrixMediaLoader, private val matrixMediaLoader: MatrixMediaLoader,
@Assisted private val mediaSource: MediaSource, @Assisted private val mediaSource: MediaSource,
@Assisted("mimeType") private val mimeType: String?, @Assisted("mimeType") private val mimeType: String?,
@ -101,7 +103,7 @@ class DefaultVoiceMessageMediaRepo @AssistedInject constructor(
} }
} }
private val cachedFile: File? = mxcUri2FilePath(mediaSource.url)?.let { private val cachedFile: File? = mxcTools.mxcUri2FilePath(mediaSource.url)?.let {
File("${cacheDir.path}/$CACHE_VOICE_SUBDIR/$it") File("${cacheDir.path}/$CACHE_VOICE_SUBDIR/$it")
} }
} }
@ -110,24 +112,3 @@ class DefaultVoiceMessageMediaRepo @AssistedInject constructor(
* Subdirectory of the application's cache directory where voice messages are stored. * Subdirectory of the application's cache directory where voice messages are stored.
*/ */
private const val CACHE_VOICE_SUBDIR = "temp/voice" private const val CACHE_VOICE_SUBDIR = "temp/voice"
/**
* Regex to match a Matrix Content (mxc://) URI.
*
* See: https://spec.matrix.org/v1.8/client-server-api/#matrix-content-mxc-uris
*/
private val mxcRegex = Regex("""^mxc:\/\/([^\/]+)\/([^\/]+)$""")
/**
* Sanitizes an mxcUri to be used as a relative file path.
*
* @param mxcUri the Matrix Content (mxc://) URI of the voice message.
* @return the relative file path as "<server-name>/<media-id>" or null if the mxcUri is invalid.
*/
private fun mxcUri2FilePath(mxcUri: String): String? = mxcRegex.matchEntire(mxcUri)?.let { match ->
buildString {
append(match.groupValues[1])
append("/")
append(match.groupValues[2])
}
}

2
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/DefaultVoiceMessageMediaRepoTest.kt

@ -20,6 +20,7 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.mxc.MxcTools
import io.element.android.libraries.matrix.test.media.FakeMediaLoader import io.element.android.libraries.matrix.test.media.FakeMediaLoader
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
@ -139,6 +140,7 @@ private fun createDefaultVoiceMessageMediaRepo(
mxcUri: String = MXC_URI, mxcUri: String = MXC_URI,
) = DefaultVoiceMessageMediaRepo( ) = DefaultVoiceMessageMediaRepo(
cacheDir = temporaryFolder.root, cacheDir = temporaryFolder.root,
mxcTools = MxcTools(),
matrixMediaLoader = matrixMediaLoader, matrixMediaLoader = matrixMediaLoader,
mediaSource = MediaSource( mediaSource = MediaSource(
url = mxcUri, url = mxcUri,

42
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt

@ -0,0 +1,42 @@
/*
* Copyright (c) 2023 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 io.element.android.libraries.matrix.api.mxc
import javax.inject.Inject
class MxcTools @Inject constructor() {
/**
* Regex to match a Matrix Content (mxc://) URI.
*
* See: https://spec.matrix.org/v1.8/client-server-api/#matrix-content-mxc-uris
*/
private val mxcRegex = Regex("""^mxc://([^/]+)/([^/]+)$""")
/**
* Sanitizes an mxcUri to be used as a relative file path.
*
* @param mxcUri the Matrix Content (mxc://) URI of the file.
* @return the relative file path as "<server-name>/<media-id>" or null if the mxcUri is invalid.
*/
fun mxcUri2FilePath(mxcUri: String): String? = mxcRegex.matchEntire(mxcUri)?.let { match ->
buildString {
append(match.groupValues[1])
append("/")
append(match.groupValues[2])
}
}
}

39
libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/mxc/MxcTools.kt

@ -0,0 +1,39 @@
/*
* Copyright (c) 2023 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 io.element.android.libraries.matrix.api.mxc
import com.google.common.truth.Truth.assertThat
import org.junit.Test
class MxcToolsTest {
@Test
fun `mxcUri2FilePath returns extracted path`() {
val mxcTools = MxcTools()
val mxcUri = "mxc://server.org/abc123"
val filePath = mxcTools.mxcUri2FilePath(mxcUri)
assertThat(filePath).isEqualTo("server.org/abc123")
}
@Test
fun `mxcUri2FilePath returns null for invalid data`() {
val mxcTools = MxcTools()
assertThat(mxcTools.mxcUri2FilePath("")).isNull()
assertThat(mxcTools.mxcUri2FilePath("mxc://server.org")).isNull()
assertThat(mxcTools.mxcUri2FilePath("mxc://server.org/")).isNull()
assertThat(mxcTools.mxcUri2FilePath("m://server.org/abc123")).isNull()
}
}

25
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationMediaRepo.kt

@ -24,6 +24,7 @@ import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.CacheDirectory import io.element.android.libraries.di.CacheDirectory
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.mxc.MxcTools
import java.io.File import java.io.File
/** /**
@ -68,6 +69,7 @@ interface NotificationMediaRepo {
class DefaultNotificationMediaRepo @AssistedInject constructor( class DefaultNotificationMediaRepo @AssistedInject constructor(
@CacheDirectory private val cacheDir: File, @CacheDirectory private val cacheDir: File,
private val mxcTools: MxcTools,
@Assisted private val client: MatrixClient, @Assisted private val client: MatrixClient,
) : NotificationMediaRepo { ) : NotificationMediaRepo {
@ -107,7 +109,7 @@ class DefaultNotificationMediaRepo @AssistedInject constructor(
} }
} }
private fun MediaSource.cachedFile(): File? = mxcUri2FilePath(url)?.let { private fun MediaSource.cachedFile(): File? = mxcTools.mxcUri2FilePath(url)?.let {
File("${cacheDir.path}/$CACHE_NOTIFICATION_SUBDIR/$it") File("${cacheDir.path}/$CACHE_NOTIFICATION_SUBDIR/$it")
} }
} }
@ -116,24 +118,3 @@ class DefaultNotificationMediaRepo @AssistedInject constructor(
* Subdirectory of the application's cache directory where file are stored. * Subdirectory of the application's cache directory where file are stored.
*/ */
private const val CACHE_NOTIFICATION_SUBDIR = "temp/notif" private const val CACHE_NOTIFICATION_SUBDIR = "temp/notif"
/**
* Regex to match a Matrix Content (mxc://) URI.
*
* See: https://spec.matrix.org/v1.8/client-server-api/#matrix-content-mxc-uris
*/
private val mxcRegex = Regex("""^mxc:\/\/([^\/]+)\/([^\/]+)$""")
/**
* Sanitizes an mxcUri to be used as a relative file path.
*
* @param mxcUri the Matrix Content (mxc://) URI of the file.
* @return the relative file path as "<server-name>/<media-id>" or null if the mxcUri is invalid.
*/
private fun mxcUri2FilePath(mxcUri: String): String? = mxcRegex.matchEntire(mxcUri)?.let { match ->
buildString {
append(match.groupValues[1])
append("/")
append(match.groupValues[2])
}
}

Loading…
Cancel
Save