Simplify ConflictResolveDialog

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-08-21 14:07:44 +02:00
parent ae5064d9a5
commit 9dcdb7d05b
No known key found for this signature in database
GPG key ID: 4E577DC593B59BDF
4 changed files with 109 additions and 89 deletions

View file

@ -0,0 +1,20 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.utils.extensions
import android.os.Parcel
import android.os.Parcelable
inline fun <reified T : Parcelable> Parcel.readParcelableCompat(classLoader: ClassLoader?): T? {
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
readParcelable(classLoader, T::class.java)
} else {
@Suppress("DEPRECATION")
readParcelable(classLoader)
}
}

View file

@ -9,6 +9,7 @@
*/
package com.owncloud.android.ui.activity
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
@ -114,33 +115,29 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
}
private fun handleFolderConflict(decision: Decision) {
offlineOperationPath?.let { path ->
newFile?.let { serverFile ->
val offlineOperation = fileDataStorageManager.offlineOperationDao.getByPath(path)
val path = offlineOperationPath ?: return
val serverFile = newFile ?: return
val offlineOperation = fileDataStorageManager.offlineOperationDao.getByPath(path) ?: return
offlineOperation?.let { entity ->
when(decision) {
Decision.KEEP_OFFLINE_FOLDER -> {
fileOperationsHelper?.removeFiles(listOf(serverFile), false, false)
backgroundJobManager.startOfflineOperations()
}
Decision.KEEP_SERVER_FOLDER -> {
fileDataStorageManager.offlineOperationDao.deleteByPath(path)
}
Decision.KEEP_BOTH_FOLDER -> {
fileDataStorageManager.keepOfflineOperationAndServerFile(entity)
backgroundJobManager.startOfflineOperations()
}
else -> Unit
}
offlineOperationNotificationManager.dismissNotification(offlineOperation.id)
}
when(decision) {
Decision.KEEP_OFFLINE_FOLDER -> {
fileOperationsHelper?.removeFiles(listOf(serverFile), false, false)
backgroundJobManager.startOfflineOperations()
}
Decision.KEEP_SERVER_FOLDER -> {
fileDataStorageManager.offlineOperationDao.deleteByPath(path)
}
Decision.KEEP_BOTH_FOLDER -> {
fileDataStorageManager.keepOfflineOperationAndServerFile(offlineOperation)
backgroundJobManager.startOfflineOperations()
}
else -> Unit
}
offlineOperationNotificationManager.dismissNotification(offlineOperation.id)
}
private fun keepLocal(file: OCFile?, upload: OCUpload?, user: User) {
@ -230,7 +227,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
return
}
val (ft, user) = prepareDialog()
val (ft, _) = prepareDialog()
val dialog = ConflictsResolveDialog.newInstance(
this,
offlineOperation,
@ -268,6 +265,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
}
}
@SuppressLint("CommitTransaction")
private fun prepareDialog(): Pair<FragmentTransaction, User> {
val userOptional = user
if (!userOptional.isPresent) {
@ -292,7 +290,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
val dialog = ConflictsResolveDialog.newInstance(
this,
newFile!!,
existingFile,
existingFile!!,
user
)
dialog.show(ft, "conflictDialog")

View file

@ -106,16 +106,13 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
data = savedInstanceState.getParcelableArgument(CONFLICT_DATA, ConflictDialogData::class.java)
leftDataFile = savedInstanceState.getSerializableArgument(LEFT_FILE, File::class.java)
rightDataFile = savedInstanceState.getParcelableArgument(RIGHT_FILE, OCFile::class.java)
user = savedInstanceState.getParcelableArgument(USER, User::class.java)
} else if (arguments != null) {
data = arguments.getParcelableArgument(CONFLICT_DATA, ConflictDialogData::class.java)
leftDataFile = arguments.getSerializableArgument(LEFT_FILE, File::class.java)
rightDataFile = arguments.getParcelableArgument(RIGHT_FILE, OCFile::class.java)
user = arguments.getParcelableArgument(USER, User::class.java)
val bundle = savedInstanceState ?: arguments
if (bundle != null) {
data = bundle.getParcelableArgument(ARG_CONFLICT_DATA, ConflictDialogData::class.java)
leftDataFile = bundle.getSerializableArgument(ARG_LEFT_FILE, File::class.java)
rightDataFile = bundle.getParcelableArgument(ARG_RIGHT_FILE, OCFile::class.java)
user = bundle.getParcelableArgument(ARG_USER, User::class.java)
} else {
Toast.makeText(context, "Failed to create conflict dialog", Toast.LENGTH_LONG).show()
}
@ -124,45 +121,57 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.run {
putParcelable(CONFLICT_DATA, data)
putParcelable(ARG_CONFLICT_DATA, data)
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
binding = ConflictResolveDialogBinding.inflate(requireActivity().layoutInflater)
viewThemeUtils.platform.themeCheckbox(binding.leftCheckbox)
viewThemeUtils.platform.themeCheckbox(binding.rightCheckbox)
val builder = createDialogBuilder()
val builder = MaterialAlertDialogBuilder(requireContext())
setupUI()
setOnClickListeners()
viewThemeUtils.run {
platform.themeCheckbox(binding.leftCheckbox)
platform.themeCheckbox(binding.rightCheckbox)
dialog.colorMaterialAlertDialogBackground(requireContext(), builder)
}
return builder.create()
}
private fun createDialogBuilder(): MaterialAlertDialogBuilder {
return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
.setPositiveButton(R.string.common_ok) { _: DialogInterface?, _: Int ->
val decision = when {
binding.leftCheckbox.isChecked && binding.rightCheckbox.isChecked ->
if (data?.folderName == null) Decision.KEEP_BOTH_FOLDER else Decision.KEEP_BOTH
binding.leftCheckbox.isChecked ->
if (data?.folderName == null) Decision.KEEP_OFFLINE_FOLDER else Decision.KEEP_LOCAL
binding.rightCheckbox.isChecked ->
if (data?.folderName == null) Decision.KEEP_SERVER_FOLDER else Decision.KEEP_SERVER
else -> null
}
decision?.let { listener?.conflictDecisionMade(it) }
okButtonClick()
}
.setNegativeButton(R.string.common_cancel) { _: DialogInterface?, _: Int ->
listener?.conflictDecisionMade(Decision.CANCEL)
}
.setTitle(data?.folderName)
}
setupUI()
setOnClickListeners()
private fun okButtonClick() {
binding.run {
val isFolderNameNotExists = (data?.folderName == null)
val decision = when {
leftCheckbox.isChecked && rightCheckbox.isChecked ->
if (isFolderNameNotExists) Decision.KEEP_BOTH_FOLDER else Decision.KEEP_BOTH
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.rightFileContainer.context, builder)
leftCheckbox.isChecked ->
if (isFolderNameNotExists) Decision.KEEP_OFFLINE_FOLDER else Decision.KEEP_LOCAL
return builder.create()
rightCheckbox.isChecked ->
if (isFolderNameNotExists) Decision.KEEP_SERVER_FOLDER else Decision.KEEP_SERVER
else -> null
}
decision?.let { listener?.conflictDecisionMade(it) }
}
}
private fun setupUI() {
@ -284,25 +293,26 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
}
companion object {
private const val CONFLICT_DATA = "CONFLICT_DATA"
private const val LEFT_FILE = "KEY_LEFT_FILE"
private const val RIGHT_FILE = "KEY_RIGHT_FILE"
private const val USER = "user"
private const val ARG_CONFLICT_DATA = "CONFLICT_DATA"
private const val ARG_LEFT_FILE = "LEFT_FILE"
private const val ARG_RIGHT_FILE = "RIGHT_FILE"
private const val ARG_USER = "USER"
@JvmStatic
fun newInstance(
context: Context,
leftFile: OCFile,
rightFile: OCFile?,
rightFile: OCFile,
user: User?
): ConflictsResolveDialog {
val file = File(leftFile.storagePath)
val conflictData = getFileConflictData(file, rightFile, context)
val bundle = Bundle().apply {
putParcelable(CONFLICT_DATA, getConflictDataForFileConflict(file, rightFile, context))
putSerializable(LEFT_FILE, file)
putParcelable(RIGHT_FILE, rightFile)
putParcelable(USER, user)
putParcelable(ARG_CONFLICT_DATA, conflictData)
putSerializable(ARG_LEFT_FILE, file)
putParcelable(ARG_RIGHT_FILE, rightFile)
putParcelable(ARG_USER, user)
}
return ConflictsResolveDialog().apply {
@ -314,13 +324,13 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
fun newInstance(
context: Context,
offlineOperation: OfflineOperationEntity,
rightFile: OCFile?,
rightFile: OCFile,
): ConflictsResolveDialog {
val conflictData = getConflictDataForFolderConflict(offlineOperation, rightFile, context)
val conflictData = getFolderConflictData(offlineOperation, rightFile, context)
val bundle = Bundle().apply {
putParcelable(CONFLICT_DATA, conflictData)
putParcelable(RIGHT_FILE, rightFile)
putParcelable(ARG_CONFLICT_DATA, conflictData)
putParcelable(ARG_RIGHT_FILE, rightFile)
}
return ConflictsResolveDialog().apply {
@ -329,9 +339,9 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
}
@JvmStatic
fun getConflictDataForFolderConflict(
private fun getFolderConflictData(
offlineOperation: OfflineOperationEntity,
rightFile: OCFile?,
rightFile: OCFile,
context: Context
): ConflictDialogData {
val folderName = null
@ -343,8 +353,8 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
val leftCheckBoxData = ConflictFileData(leftTitle, leftTimestamp.toString(), leftFileSize)
val rightTitle = context.getString(R.string.prefs_synced_folders_remote_path_title)
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile?.modificationTimestamp ?: 0)
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile?.fileLength ?: 0)
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile.modificationTimestamp)
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile.fileLength)
val rightCheckBoxData = ConflictFileData(rightTitle, rightTimestamp.toString(), rightFileSize)
val title = context.getString(R.string.conflict_folder_headline)
@ -353,12 +363,12 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
}
@JvmStatic
fun getConflictDataForFileConflict(
private fun getFileConflictData(
file: File,
rightFile: OCFile?,
rightFile: OCFile,
context: Context
): ConflictDialogData {
val parentFile = rightFile?.remotePath?.let { File(it).parentFile }
val parentFile = File(rightFile.remotePath).parentFile
val folderName = if (parentFile != null) {
String.format(context.getString(R.string.in_folder), parentFile.absolutePath)
} else {
@ -371,8 +381,8 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
val leftCheckBoxData = ConflictFileData(leftTitle, leftTimestamp.toString(), leftFileSize)
val rightTitle = context.getString(R.string.conflict_server_file)
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile?.modificationTimestamp ?: 0)
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile?.fileLength ?: 0)
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile.modificationTimestamp)
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile.fileLength)
val rightCheckBoxData = ConflictFileData(rightTitle, rightTimestamp.toString(), rightFileSize)
val title = context.getString(R.string.choose_which_file)

View file

@ -9,6 +9,7 @@ package com.owncloud.android.ui.dialog.parcel
import android.os.Parcel
import android.os.Parcelable
import com.nextcloud.utils.extensions.readParcelableCompat
data class ConflictDialogData(
val folderName: String?,
@ -66,12 +67,3 @@ data class ConflictFileData(
override fun newArray(size: Int): Array<ConflictFileData?> = arrayOfNulls(size)
}
}
inline fun <reified T : Parcelable> Parcel.readParcelableCompat(classLoader: ClassLoader?): T? {
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
readParcelable(classLoader, T::class.java)
} else {
@Suppress("DEPRECATION")
readParcelable(classLoader)
}
}