diff --git a/vector/src/main/java/im/vector/riotx/core/utils/ExternalApplicationsUtil.kt b/vector/src/main/java/im/vector/riotx/core/utils/ExternalApplicationsUtil.kt index 0a20b9d7bf..d93d4e9089 100644 --- a/vector/src/main/java/im/vector/riotx/core/utils/ExternalApplicationsUtil.kt +++ b/vector/src/main/java/im/vector/riotx/core/utils/ExternalApplicationsUtil.kt @@ -26,6 +26,7 @@ import android.net.Uri import android.os.Build import android.provider.Browser import android.provider.MediaStore +import android.widget.Toast import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsSession import androidx.core.content.ContextCompat @@ -33,6 +34,7 @@ import androidx.core.content.FileProvider import androidx.fragment.app.Fragment import im.vector.riotx.BuildConfig import im.vector.riotx.R +import im.vector.riotx.features.notifications.NotificationUtils import okio.buffer import okio.sink import okio.source @@ -297,7 +299,7 @@ fun shareMedia(context: Context, file: File, mediaMimeType: String?) { } } -fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String?): Boolean { +fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String?, notificationUtils: NotificationUtils) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val externalContentUri: Uri val values = ContentValues() @@ -335,7 +337,10 @@ fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String values.put(MediaStore.Downloads.DATE_TAKEN, System.currentTimeMillis()) } } - context.contentResolver.insert(externalContentUri, values)?.let { uri -> + val uri = context.contentResolver.insert(externalContentUri, values) + if (uri == null) { + Toast.makeText(context, R.string.error_saving_media_file, Toast.LENGTH_LONG).show() + } else { val source = file.inputStream().source().buffer() context.contentResolver.openOutputStream(uri)?.sink()?.buffer()?.let { sink -> source.use { input -> @@ -344,6 +349,13 @@ fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String } } } + notificationUtils.buildDownloadFileNotification( + uri, + title, + mediaMimeType ?: "application/octet-stream" + ).let { notification -> + notificationUtils.showNotificationMessage("DL", uri.hashCode(), notification) + } } // TODO add notification? } else { @@ -352,9 +364,7 @@ fun saveMedia(context: Context, file: File, title: String, mediaMimeType: String mediaScanIntent.data = Uri.fromFile(file) context.sendBroadcast(mediaScanIntent) } - return true } - return false } /** diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 5c70502c6f..84e0388f18 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -1366,17 +1366,13 @@ class RoomDetailFragment @Inject constructor( callback = object : MatrixCallback { override fun onSuccess(data: File) { if (isAdded) { - val saved = saveMedia( + saveMedia( context = requireContext(), file = data, title = action.messageContent.body, - mediaMimeType = getMimeTypeFromUri(requireContext(), data.toUri()) + mediaMimeType = action.messageContent.mimeType ?: getMimeTypeFromUri(requireContext(), data.toUri()), + notificationUtils = notificationUtils ) - if (saved) { - Toast.makeText(requireContext(), R.string.media_file_added_to_gallery, Toast.LENGTH_LONG).show() - } else { - Toast.makeText(requireContext(), R.string.error_adding_media_file_to_gallery, Toast.LENGTH_LONG).show() - } } } } diff --git a/vector/src/main/java/im/vector/riotx/features/roomprofile/uploads/RoomUploadsFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomprofile/uploads/RoomUploadsFragment.kt index 99aeb4231b..47dab994b4 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomprofile/uploads/RoomUploadsFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomprofile/uploads/RoomUploadsFragment.kt @@ -22,7 +22,6 @@ import androidx.core.net.toUri import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayoutMediator import im.vector.matrix.android.api.util.toMatrixItem import im.vector.riotx.R @@ -33,6 +32,7 @@ import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.utils.saveMedia import im.vector.riotx.core.utils.shareMedia import im.vector.riotx.features.home.AvatarRenderer +import im.vector.riotx.features.notifications.NotificationUtils import im.vector.riotx.features.roomprofile.RoomProfileArgs import kotlinx.android.synthetic.main.fragment_room_uploads.* import javax.inject.Inject @@ -40,7 +40,8 @@ import javax.inject.Inject class RoomUploadsFragment @Inject constructor( private val viewModelFactory: RoomUploadsViewModel.Factory, private val stringProvider: StringProvider, - private val avatarRenderer: AvatarRenderer + private val avatarRenderer: AvatarRenderer, + private val notificationUtils: NotificationUtils ) : VectorBaseFragment(), RoomUploadsViewModel.Factory by viewModelFactory { private val roomProfileArgs: RoomProfileArgs by args() @@ -70,17 +71,13 @@ class RoomUploadsFragment @Inject constructor( shareMedia(requireContext(), it.file, getMimeTypeFromUri(requireContext(), it.file.toUri())) } is RoomUploadsViewEvents.FileReadyForSaving -> { - val saved = saveMedia( + saveMedia( context = requireContext(), file = it.file, title = it.title, - mediaMimeType = getMimeTypeFromUri(requireContext(), it.file.toUri()) + mediaMimeType = getMimeTypeFromUri(requireContext(), it.file.toUri()), + notificationUtils = notificationUtils ) - if (saved) { - Snackbar.make(roomUploadsCoordinator, R.string.media_file_added_to_gallery, Snackbar.LENGTH_LONG).show() - } else { - Snackbar.make(roomUploadsCoordinator, R.string.error_adding_media_file_to_gallery, Snackbar.LENGTH_LONG).show() - } } is RoomUploadsViewEvents.Failure -> showFailure(it.throwable) }.exhaustive diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 05aa7d27bb..d8aad6f539 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2404,6 +2404,7 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming Media file added to the Gallery Could not add media file to the Gallery + Could not save media file Set a new account password… Use the latest Riot on your other devices, Riot Web, Riot Desktop, Riot iOS, RiotX for Android, or another cross-signing capable Matrix client