Browse Source

MediaViewer: improve actions (save on disk and share)

feature/fga/small_timeline_improvements
ganfra 1 year ago
parent
commit
fa63ed1faf
  1. 3
      app/src/main/AndroidManifest.xml
  2. 11
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/AndroidLocalMediaActions.kt
  3. 6
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt
  4. 9
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt
  5. 2
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/media/MatrixMediaLoader.kt
  6. 4
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt
  7. 2
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/media/FakeMediaLoader.kt

3
app/src/main/AndroidManifest.xml

@ -17,6 +17,9 @@ @@ -17,6 +17,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- To be able to install APK from the application -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:name=".ElementXApplication"
android:allowBackup="true"

11
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/AndroidLocalMediaActions.kt

@ -113,16 +113,9 @@ class AndroidLocalMediaActions @Inject constructor( @@ -113,16 +113,9 @@ class AndroidLocalMediaActions @Inject constructor(
}
/**
* Tries to extract a file from the uri and rename it using the local media name if defined.
* Tries to extract a file from the uri.
*/
private fun LocalMedia.toFile(): File {
val uriAsFile = uri.toFile()
return if (name != null) {
File(uriAsFile.parentFile, name).apply {
uriAsFile.renameTo(this)
}
} else {
uriAsFile
}
return uri.toFile()
}
}

6
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt

@ -94,7 +94,11 @@ class MediaViewerPresenter @AssistedInject constructor( @@ -94,7 +94,11 @@ class MediaViewerPresenter @AssistedInject constructor(
private fun CoroutineScope.downloadMedia(mediaFile: MutableState<MediaFile?>, localMedia: MutableState<Async<LocalMedia>>) = launch {
localMedia.value = Async.Loading()
mediaLoader.downloadMediaFile(inputs.mediaSource, inputs.mimeType)
mediaLoader.downloadMediaFile(
source = inputs.mediaSource,
mimeType = inputs.mimeType,
body = inputs.name
)
.onSuccess {
mediaFile.value = it
}.mapCatching { mediaFile ->

9
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt

@ -104,7 +104,11 @@ fun MediaViewerView( @@ -104,7 +104,11 @@ fun MediaViewerView(
Scaffold(modifier,
topBar = {
MediaViewerTopBar(onBackPressed, state.eventSink)
MediaViewerTopBar(
actionsEnabled = state.downloadedMedia is Async.Success,
onBackPressed = onBackPressed,
eventSink = state.eventSink
)
},
snackbarHost = {
SnackbarHost(snackbarHostState) { data ->
@ -145,6 +149,7 @@ fun MediaViewerView( @@ -145,6 +149,7 @@ fun MediaViewerView(
@Composable
private fun MediaViewerTopBar(
actionsEnabled : Boolean,
onBackPressed: () -> Unit,
eventSink: (MediaViewerEvents) -> Unit,
) {
@ -153,6 +158,7 @@ private fun MediaViewerTopBar( @@ -153,6 +158,7 @@ private fun MediaViewerTopBar(
navigationIcon = { BackButton(onClick = onBackPressed) },
actions = {
IconButton(
enabled = actionsEnabled,
onClick = {
eventSink(MediaViewerEvents.Share)
},
@ -160,6 +166,7 @@ private fun MediaViewerTopBar( @@ -160,6 +166,7 @@ private fun MediaViewerTopBar(
Icon(imageVector = Icons.Default.Share, contentDescription = stringResource(id = string.action_share))
}
IconButton(
enabled = actionsEnabled,
onClick = {
eventSink(MediaViewerEvents.SaveOnDisk)
},

2
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/media/MatrixMediaLoader.kt

@ -36,5 +36,5 @@ interface MatrixMediaLoader { @@ -36,5 +36,5 @@ interface MatrixMediaLoader {
* @param mimeType: optional mime type
* @return a [Result] of [MediaFile]
*/
suspend fun downloadMediaFile(source: MediaSource, mimeType: String?): Result<MediaFile>
suspend fun downloadMediaFile(source: MediaSource, mimeType: String?, body: String?): Result<MediaFile>
}

4
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt

@ -59,13 +59,13 @@ class RustMediaLoader( @@ -59,13 +59,13 @@ class RustMediaLoader(
}
}
override suspend fun downloadMediaFile(source: MediaSource, mimeType: String?): Result<MediaFile> =
override suspend fun downloadMediaFile(source: MediaSource, mimeType: String?, body: String?): Result<MediaFile> =
withContext(dispatchers.io) {
runCatching {
source.toRustMediaSource().use { mediaSource ->
val mediaFile = innerClient.getMediaFile(
mediaSource = mediaSource,
body = null,
body = body,
mimeType = mimeType ?: "application/octet-stream"
)
RustMediaFile(mediaFile)

2
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/media/FakeMediaLoader.kt

@ -44,7 +44,7 @@ class FakeMediaLoader : MatrixMediaLoader { @@ -44,7 +44,7 @@ class FakeMediaLoader : MatrixMediaLoader {
}
}
override suspend fun downloadMediaFile(source: MediaSource, mimeType: String?): Result<MediaFile> {
override suspend fun downloadMediaFile(source: MediaSource, mimeType: String?, body: String?): Result<MediaFile> {
delay(FAKE_DELAY_IN_MS)
return if (shouldFail) {
Result.failure(RuntimeException())

Loading…
Cancel
Save