Skip to content

Commit

Permalink
feat: Centralize shared code in abstract class
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasBourdin88 committed Nov 22, 2024
1 parent 67f6360 commit 71252af
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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<Uri>.openKDriveOrPlayStore(context: Context): Intent? {
return if (canSaveOnKDrive(context)) {
saveToDriveIntent()
} else {
context.goToPlayStore(DRIVE_PACKAGE)
null
}
}

private fun ArrayList<Uri>.saveToDriveIntent(): Intent {
return Intent().apply {
component = ComponentName(DRIVE_PACKAGE, SAVE_EXTERNAL_ACTIVITY_CLASS)
action = Intent.ACTION_SEND_MULTIPLE
putParcelableArrayListExtra(Intent.EXTRA_STREAM, this@saveToDriveIntent)
}
}

Expand Down
35 changes: 35 additions & 0 deletions app/src/main/java/com/infomaniak/mail/utils/KDriveUtils.kt
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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<Uri>.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()
Expand All @@ -91,14 +72,6 @@ object AttachmentExtensions {
}
}

private fun ArrayList<Uri>.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)
Expand All @@ -120,8 +93,6 @@ object AttachmentExtensions {
}
}



fun Attachment.executeIntent(
context: Context,
intentType: AttachmentIntentType,
Expand Down

0 comments on commit 71252af

Please sign in to comment.