diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadAttachmentProgressDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadAttachmentProgressDialog.kt index c63933bb92b..f34d0744fa8 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadAttachmentProgressDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadAttachmentProgressDialog.kt @@ -17,59 +17,23 @@ */ package com.infomaniak.mail.ui.main.thread.actions -import android.app.Dialog -import android.os.Bundle -import android.view.KeyEvent -import androidx.appcompat.content.res.AppCompatResources -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels -import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.infomaniak.lib.core.R -import com.infomaniak.lib.core.utils.SnackbarUtils.showSnackbar import com.infomaniak.lib.core.utils.setBackNavigationResult -import com.infomaniak.mail.databinding.DialogDownloadProgressBinding -import com.infomaniak.mail.ui.MainViewModel import com.infomaniak.mail.utils.extensions.AttachmentExtensions import com.infomaniak.mail.utils.extensions.AttachmentExtensions.getIntentOrGoToPlayStore import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch @AndroidEntryPoint -class DownloadAttachmentProgressDialog : DialogFragment() { - - private val binding by lazy { DialogDownloadProgressBinding.inflate(layoutInflater) } +class DownloadAttachmentProgressDialog : DownloadProgressDialog() { private val navigationArgs: DownloadAttachmentProgressDialogArgs by navArgs() - private val mainViewModel: MainViewModel by activityViewModels() private val downloadAttachmentViewModel: DownloadAttachmentViewModel by viewModels() - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - isCancelable = false - val iconDrawable = AppCompatResources.getDrawable(requireContext(), navigationArgs.attachmentType.icon) - binding.icon.setImageDrawable(iconDrawable) - - return MaterialAlertDialogBuilder(requireContext()) - .setTitle(navigationArgs.attachmentName) - .setView(binding.root) - .setOnKeyListener { _, keyCode, event -> - if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { - findNavController().popBackStack() - true - } else false - } - .create() - } - - override fun onStart() { - super.onStart() - downloadAttachment() - } + override val dialogTitle: String? by lazy { navigationArgs.attachmentName } + override val dialogIconDrawableRes: Int? by lazy { navigationArgs.attachmentType.icon } - private fun downloadAttachment() { + override fun download() { downloadAttachmentViewModel.downloadAttachment().observe(this) { cachedAttachment -> if (cachedAttachment == null) { popBackStackWithError() @@ -80,13 +44,4 @@ class DownloadAttachmentProgressDialog : DialogFragment() { } } } - - private fun popBackStackWithError() { - lifecycleScope.launch { - mainViewModel.isNetworkAvailable.first { it != null }?.let { isNetworkAvailable -> - showSnackbar(title = if (isNetworkAvailable) R.string.anErrorHasOccurred else R.string.noConnection) - findNavController().popBackStack() - } - } - } } diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadProgressDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadProgressDialog.kt new file mode 100644 index 00000000000..36880ea3a56 --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadProgressDialog.kt @@ -0,0 +1,81 @@ +/* + * Infomaniak Mail - Android + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.mail.ui.main.thread.actions + +import android.app.Dialog +import android.os.Bundle +import android.view.KeyEvent +import androidx.annotation.DrawableRes +import androidx.appcompat.content.res.AppCompatResources +import androidx.core.view.isVisible +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.infomaniak.lib.core.R +import com.infomaniak.lib.core.utils.SnackbarUtils.showSnackbar +import com.infomaniak.mail.databinding.DialogDownloadProgressBinding +import com.infomaniak.mail.ui.MainViewModel +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch + +@AndroidEntryPoint +abstract class DownloadProgressDialog : DialogFragment() { + protected val binding by lazy { DialogDownloadProgressBinding.inflate(layoutInflater) } + protected val mainViewModel: MainViewModel by activityViewModels() + abstract val dialogTitle: String? + @get:DrawableRes abstract val dialogIconDrawableRes: Int? + + override fun onStart() { + download() + super.onStart() + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val context = requireContext() + + dialogIconDrawableRes?.let { binding.icon.setImageDrawable(AppCompatResources.getDrawable(requireContext(), it)) } + binding.icon.isVisible = dialogIconDrawableRes == null + + isCancelable = false + + return MaterialAlertDialogBuilder(context) + .setTitle(dialogTitle) + .setView(binding.root) + .setOnKeyListener { _, keyCode, event -> + if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { + findNavController().popBackStack() + true + } else false + } + .create() + } + + abstract fun download() + + protected fun popBackStackWithError() { + lifecycleScope.launch { + mainViewModel.isNetworkAvailable.first { it != null }?.let { isNetworkAvailable -> + showSnackbar(title = if (isNetworkAvailable) R.string.anErrorHasOccurred else R.string.noConnection) + findNavController().popBackStack() + } + } + } +} diff --git a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadThreadsProgressDialog.kt b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadThreadsProgressDialog.kt index 263de5b674d..b13af290c2f 100644 --- a/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadThreadsProgressDialog.kt +++ b/app/src/main/java/com/infomaniak/mail/ui/main/thread/actions/DownloadThreadsProgressDialog.kt @@ -17,66 +17,29 @@ */ package com.infomaniak.mail.ui.main.thread.actions -import android.app.Dialog -import android.os.Bundle -import android.view.KeyEvent -import androidx.core.view.isVisible -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.activityViewModels +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.net.Uri import androidx.fragment.app.viewModels -import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.infomaniak.lib.core.utils.SnackbarUtils.showSnackbar +import com.infomaniak.lib.core.utils.goToPlayStore import com.infomaniak.lib.core.utils.setBackNavigationResult import com.infomaniak.mail.R -import com.infomaniak.mail.databinding.DialogDownloadProgressBinding -import com.infomaniak.mail.ui.MainViewModel -import com.infomaniak.mail.utils.extensions.AttachmentExtensions.openKDriveOrPlayStore +import com.infomaniak.mail.utils.KDriveUtils.DRIVE_PACKAGE +import com.infomaniak.mail.utils.KDriveUtils.SAVE_EXTERNAL_ACTIVITY_CLASS +import com.infomaniak.mail.utils.KDriveUtils.canSaveOnKDrive import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import com.infomaniak.lib.core.R as RCore @AndroidEntryPoint -class DownloadThreadsProgressDialog : DialogFragment() { - private val binding by lazy { DialogDownloadProgressBinding.inflate(layoutInflater) } - private val mainViewModel: MainViewModel by activityViewModels() +class DownloadThreadsProgressDialog : DownloadProgressDialog() { private val downloadThreadsViewModel: DownloadThreadsViewModel by viewModels() private val navigationArgs: DownloadThreadsProgressDialogArgs by navArgs() + override val dialogTitle: String? by lazy { getDialogTitleFromArgs() } + override val dialogIconDrawableRes: Int? by lazy { null } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val context = requireContext() - - isCancelable = false - binding.icon.isVisible = false - - val textTitleDialog = if (navigationArgs.messageUids.size == 1) { - navigationArgs.nameFirstMessage - } else { - context.resources.getQuantityString(R.plurals.downloadingEmailsTitle, 1, navigationArgs.messageUids.size) - // TODO LOOK - } - - return MaterialAlertDialogBuilder(context) - .setTitle(textTitleDialog) - .setView(binding.root) - .setOnKeyListener { _, keyCode, event -> - if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { - findNavController().popBackStack() - true - } else false - } - .create() - } - - override fun onStart() { - downloadThreads() - super.onStart() - } - - private fun downloadThreads() { + override fun download() { downloadThreadsViewModel.downloadThreads(mainViewModel.currentMailbox.value).observe(this) { threadUris -> if (threadUris == null) { popBackStackWithError() @@ -88,12 +51,26 @@ class DownloadThreadsProgressDialog : DialogFragment() { } } - private fun popBackStackWithError() { - lifecycleScope.launch { - mainViewModel.isNetworkAvailable.first { it != null }?.let { isNetworkAvailable -> - showSnackbar(title = if (isNetworkAvailable) RCore.string.anErrorHasOccurred else RCore.string.noConnection) - findNavController().popBackStack() - } + private fun getDialogTitleFromArgs() = if (navigationArgs.messageUids.size == 1) { + navigationArgs.nameFirstMessage + } else { + requireContext().resources.getQuantityString(R.plurals.downloadingEmailsTitle, 1, navigationArgs.messageUids.size) + } + + private fun ArrayList.openKDriveOrPlayStore(context: Context): Intent? { + return if (canSaveOnKDrive(context)) { + saveToDriveIntent() + } else { + context.goToPlayStore(DRIVE_PACKAGE) + null + } + } + + private fun ArrayList.saveToDriveIntent(): Intent { + return Intent().apply { + component = ComponentName(DRIVE_PACKAGE, SAVE_EXTERNAL_ACTIVITY_CLASS) + action = Intent.ACTION_SEND_MULTIPLE + putParcelableArrayListExtra(Intent.EXTRA_STREAM, this@saveToDriveIntent) } } diff --git a/app/src/main/java/com/infomaniak/mail/utils/KDriveUtils.kt b/app/src/main/java/com/infomaniak/mail/utils/KDriveUtils.kt new file mode 100644 index 00000000000..98029ef0265 --- /dev/null +++ b/app/src/main/java/com/infomaniak/mail/utils/KDriveUtils.kt @@ -0,0 +1,35 @@ +/* + * Infomaniak Mail - Android + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.mail.utils + +import android.content.Context +import android.content.pm.PackageManager +import io.sentry.Sentry + +object KDriveUtils { + const val DRIVE_PACKAGE = "com.infomaniak.drive" + const val SAVE_EXTERNAL_ACTIVITY_CLASS = "com.infomaniak.drive.ui.SaveExternalFilesActivity" + + fun canSaveOnKDrive(context: Context) = runCatching { + val packageInfo = context.packageManager.getPackageInfo(DRIVE_PACKAGE, PackageManager.GET_ACTIVITIES) + packageInfo.activities.any { it.name == SAVE_EXTERNAL_ACTIVITY_CLASS } + }.getOrElse { + Sentry.captureException(it) + false + } +} diff --git a/app/src/main/java/com/infomaniak/mail/utils/extensions/AttachmentExtensions.kt b/app/src/main/java/com/infomaniak/mail/utils/extensions/AttachmentExtensions.kt index f7016a3c271..f282c86331b 100644 --- a/app/src/main/java/com/infomaniak/mail/utils/extensions/AttachmentExtensions.kt +++ b/app/src/main/java/com/infomaniak/mail/utils/extensions/AttachmentExtensions.kt @@ -20,8 +20,6 @@ package com.infomaniak.mail.utils.extensions import android.content.ComponentName import android.content.Context import android.content.Intent -import android.content.pm.PackageManager -import android.net.Uri import android.os.Bundle import android.provider.MediaStore.Files.FileColumns import androidx.core.content.FileProvider @@ -39,6 +37,9 @@ import com.infomaniak.mail.data.models.mailbox.Mailbox import com.infomaniak.mail.ui.main.SnackbarManager import com.infomaniak.mail.ui.main.thread.actions.DownloadAttachmentProgressDialogArgs import com.infomaniak.mail.utils.AccountUtils +import com.infomaniak.mail.utils.KDriveUtils.DRIVE_PACKAGE +import com.infomaniak.mail.utils.KDriveUtils.SAVE_EXTERNAL_ACTIVITY_CLASS +import com.infomaniak.mail.utils.KDriveUtils.canSaveOnKDrive import com.infomaniak.mail.utils.SentryDebug import com.infomaniak.mail.utils.WorkerUtils.UploadMissingLocalFileException import com.infomaniak.mail.utils.extensions.AttachmentExtensions.AttachmentIntentType.OPEN_WITH @@ -56,27 +57,7 @@ object AttachmentExtensions { const val ATTACHMENT_TAG = "attachmentUpload" const val DOWNLOAD_ATTACHMENT_RESULT = "download_attachment_result" - private const val DRIVE_PACKAGE = "com.infomaniak.drive" - private const val SAVE_EXTERNAL_ACTIVITY_CLASS = "com.infomaniak.drive.ui.SaveExternalFilesActivity" - - fun ArrayList.openKDriveOrPlayStore(context: Context): Intent? { - return if (canSaveOnKDrive(context)) { - saveToDriveIntent() - } else { - context.goToPlayStore(DRIVE_PACKAGE) - null - } - } - //region Intent - private fun canSaveOnKDrive(context: Context) = runCatching { - val packageInfo = context.packageManager.getPackageInfo(DRIVE_PACKAGE, PackageManager.GET_ACTIVITIES) - packageInfo.activities.any { it.name == SAVE_EXTERNAL_ACTIVITY_CLASS } - }.getOrElse { - Sentry.captureException(it) - false - } - private fun Attachment.saveToDriveIntent(context: Context): Intent { val fileFromCache = getCacheFile(context) val lastModifiedDate = fileFromCache.lastModified() @@ -91,14 +72,6 @@ object AttachmentExtensions { } } - private fun ArrayList.saveToDriveIntent(): Intent { - return Intent().apply { - component = ComponentName(DRIVE_PACKAGE, SAVE_EXTERNAL_ACTIVITY_CLASS) - action = Intent.ACTION_SEND_MULTIPLE - putParcelableArrayListExtra(Intent.EXTRA_STREAM, this@saveToDriveIntent) - } - } - private fun Attachment.openWithIntent(context: Context): Intent { val file = getUploadLocalFile() ?: getCacheFile(context) val uri = FileProvider.getUriForFile(context, context.getString(R.string.ATTACHMENTS_AUTHORITY), file) @@ -120,8 +93,6 @@ object AttachmentExtensions { } } - - fun Attachment.executeIntent( context: Context, intentType: AttachmentIntentType,