mirror of
https://github.com/nextcloud/android.git
synced 2024-11-26 15:15:51 +03:00
Simplify ConflictResolveDialog
Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
parent
ae5064d9a5
commit
9dcdb7d05b
4 changed files with 109 additions and 89 deletions
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
package com.owncloud.android.ui.activity
|
package com.owncloud.android.ui.activity
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -114,33 +115,29 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleFolderConflict(decision: Decision) {
|
private fun handleFolderConflict(decision: Decision) {
|
||||||
offlineOperationPath?.let { path ->
|
val path = offlineOperationPath ?: return
|
||||||
newFile?.let { serverFile ->
|
val serverFile = newFile ?: return
|
||||||
val offlineOperation = fileDataStorageManager.offlineOperationDao.getByPath(path)
|
val offlineOperation = fileDataStorageManager.offlineOperationDao.getByPath(path) ?: return
|
||||||
|
|
||||||
offlineOperation?.let { entity ->
|
when(decision) {
|
||||||
when(decision) {
|
Decision.KEEP_OFFLINE_FOLDER -> {
|
||||||
Decision.KEEP_OFFLINE_FOLDER -> {
|
fileOperationsHelper?.removeFiles(listOf(serverFile), false, false)
|
||||||
fileOperationsHelper?.removeFiles(listOf(serverFile), false, false)
|
backgroundJobManager.startOfflineOperations()
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
private fun keepLocal(file: OCFile?, upload: OCUpload?, user: User) {
|
||||||
|
@ -230,7 +227,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val (ft, user) = prepareDialog()
|
val (ft, _) = prepareDialog()
|
||||||
val dialog = ConflictsResolveDialog.newInstance(
|
val dialog = ConflictsResolveDialog.newInstance(
|
||||||
this,
|
this,
|
||||||
offlineOperation,
|
offlineOperation,
|
||||||
|
@ -268,6 +265,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CommitTransaction")
|
||||||
private fun prepareDialog(): Pair<FragmentTransaction, User> {
|
private fun prepareDialog(): Pair<FragmentTransaction, User> {
|
||||||
val userOptional = user
|
val userOptional = user
|
||||||
if (!userOptional.isPresent) {
|
if (!userOptional.isPresent) {
|
||||||
|
@ -292,7 +290,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
||||||
val dialog = ConflictsResolveDialog.newInstance(
|
val dialog = ConflictsResolveDialog.newInstance(
|
||||||
this,
|
this,
|
||||||
newFile!!,
|
newFile!!,
|
||||||
existingFile,
|
existingFile!!,
|
||||||
user
|
user
|
||||||
)
|
)
|
||||||
dialog.show(ft, "conflictDialog")
|
dialog.show(ft, "conflictDialog")
|
||||||
|
|
|
@ -106,16 +106,13 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
val bundle = savedInstanceState ?: arguments
|
||||||
data = savedInstanceState.getParcelableArgument(CONFLICT_DATA, ConflictDialogData::class.java)
|
|
||||||
leftDataFile = savedInstanceState.getSerializableArgument(LEFT_FILE, File::class.java)
|
if (bundle != null) {
|
||||||
rightDataFile = savedInstanceState.getParcelableArgument(RIGHT_FILE, OCFile::class.java)
|
data = bundle.getParcelableArgument(ARG_CONFLICT_DATA, ConflictDialogData::class.java)
|
||||||
user = savedInstanceState.getParcelableArgument(USER, User::class.java)
|
leftDataFile = bundle.getSerializableArgument(ARG_LEFT_FILE, File::class.java)
|
||||||
} else if (arguments != null) {
|
rightDataFile = bundle.getParcelableArgument(ARG_RIGHT_FILE, OCFile::class.java)
|
||||||
data = arguments.getParcelableArgument(CONFLICT_DATA, ConflictDialogData::class.java)
|
user = bundle.getParcelableArgument(ARG_USER, User::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)
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, "Failed to create conflict dialog", Toast.LENGTH_LONG).show()
|
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) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.run {
|
outState.run {
|
||||||
putParcelable(CONFLICT_DATA, data)
|
putParcelable(ARG_CONFLICT_DATA, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
binding = ConflictResolveDialogBinding.inflate(requireActivity().layoutInflater)
|
binding = ConflictResolveDialogBinding.inflate(requireActivity().layoutInflater)
|
||||||
|
|
||||||
viewThemeUtils.platform.themeCheckbox(binding.leftCheckbox)
|
val builder = createDialogBuilder()
|
||||||
viewThemeUtils.platform.themeCheckbox(binding.rightCheckbox)
|
|
||||||
|
|
||||||
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)
|
.setView(binding.root)
|
||||||
.setPositiveButton(R.string.common_ok) { _: DialogInterface?, _: Int ->
|
.setPositiveButton(R.string.common_ok) { _: DialogInterface?, _: Int ->
|
||||||
val decision = when {
|
okButtonClick()
|
||||||
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) }
|
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.common_cancel) { _: DialogInterface?, _: Int ->
|
.setNegativeButton(R.string.common_cancel) { _: DialogInterface?, _: Int ->
|
||||||
listener?.conflictDecisionMade(Decision.CANCEL)
|
listener?.conflictDecisionMade(Decision.CANCEL)
|
||||||
}
|
}
|
||||||
.setTitle(data?.folderName)
|
.setTitle(data?.folderName)
|
||||||
|
}
|
||||||
|
|
||||||
setupUI()
|
private fun okButtonClick() {
|
||||||
setOnClickListeners()
|
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() {
|
private fun setupUI() {
|
||||||
|
@ -284,25 +293,26 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val CONFLICT_DATA = "CONFLICT_DATA"
|
private const val ARG_CONFLICT_DATA = "CONFLICT_DATA"
|
||||||
private const val LEFT_FILE = "KEY_LEFT_FILE"
|
private const val ARG_LEFT_FILE = "LEFT_FILE"
|
||||||
private const val RIGHT_FILE = "KEY_RIGHT_FILE"
|
private const val ARG_RIGHT_FILE = "RIGHT_FILE"
|
||||||
private const val USER = "user"
|
private const val ARG_USER = "USER"
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
context: Context,
|
context: Context,
|
||||||
leftFile: OCFile,
|
leftFile: OCFile,
|
||||||
rightFile: OCFile?,
|
rightFile: OCFile,
|
||||||
user: User?
|
user: User?
|
||||||
): ConflictsResolveDialog {
|
): ConflictsResolveDialog {
|
||||||
val file = File(leftFile.storagePath)
|
val file = File(leftFile.storagePath)
|
||||||
|
val conflictData = getFileConflictData(file, rightFile, context)
|
||||||
|
|
||||||
val bundle = Bundle().apply {
|
val bundle = Bundle().apply {
|
||||||
putParcelable(CONFLICT_DATA, getConflictDataForFileConflict(file, rightFile, context))
|
putParcelable(ARG_CONFLICT_DATA, conflictData)
|
||||||
putSerializable(LEFT_FILE, file)
|
putSerializable(ARG_LEFT_FILE, file)
|
||||||
putParcelable(RIGHT_FILE, rightFile)
|
putParcelable(ARG_RIGHT_FILE, rightFile)
|
||||||
putParcelable(USER, user)
|
putParcelable(ARG_USER, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConflictsResolveDialog().apply {
|
return ConflictsResolveDialog().apply {
|
||||||
|
@ -314,13 +324,13 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
context: Context,
|
context: Context,
|
||||||
offlineOperation: OfflineOperationEntity,
|
offlineOperation: OfflineOperationEntity,
|
||||||
rightFile: OCFile?,
|
rightFile: OCFile,
|
||||||
): ConflictsResolveDialog {
|
): ConflictsResolveDialog {
|
||||||
val conflictData = getConflictDataForFolderConflict(offlineOperation, rightFile, context)
|
val conflictData = getFolderConflictData(offlineOperation, rightFile, context)
|
||||||
|
|
||||||
val bundle = Bundle().apply {
|
val bundle = Bundle().apply {
|
||||||
putParcelable(CONFLICT_DATA, conflictData)
|
putParcelable(ARG_CONFLICT_DATA, conflictData)
|
||||||
putParcelable(RIGHT_FILE, rightFile)
|
putParcelable(ARG_RIGHT_FILE, rightFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConflictsResolveDialog().apply {
|
return ConflictsResolveDialog().apply {
|
||||||
|
@ -329,9 +339,9 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getConflictDataForFolderConflict(
|
private fun getFolderConflictData(
|
||||||
offlineOperation: OfflineOperationEntity,
|
offlineOperation: OfflineOperationEntity,
|
||||||
rightFile: OCFile?,
|
rightFile: OCFile,
|
||||||
context: Context
|
context: Context
|
||||||
): ConflictDialogData {
|
): ConflictDialogData {
|
||||||
val folderName = null
|
val folderName = null
|
||||||
|
@ -343,8 +353,8 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
val leftCheckBoxData = ConflictFileData(leftTitle, leftTimestamp.toString(), leftFileSize)
|
val leftCheckBoxData = ConflictFileData(leftTitle, leftTimestamp.toString(), leftFileSize)
|
||||||
|
|
||||||
val rightTitle = context.getString(R.string.prefs_synced_folders_remote_path_title)
|
val rightTitle = context.getString(R.string.prefs_synced_folders_remote_path_title)
|
||||||
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile?.modificationTimestamp ?: 0)
|
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile.modificationTimestamp)
|
||||||
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile?.fileLength ?: 0)
|
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile.fileLength)
|
||||||
val rightCheckBoxData = ConflictFileData(rightTitle, rightTimestamp.toString(), rightFileSize)
|
val rightCheckBoxData = ConflictFileData(rightTitle, rightTimestamp.toString(), rightFileSize)
|
||||||
|
|
||||||
val title = context.getString(R.string.conflict_folder_headline)
|
val title = context.getString(R.string.conflict_folder_headline)
|
||||||
|
@ -353,12 +363,12 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getConflictDataForFileConflict(
|
private fun getFileConflictData(
|
||||||
file: File,
|
file: File,
|
||||||
rightFile: OCFile?,
|
rightFile: OCFile,
|
||||||
context: Context
|
context: Context
|
||||||
): ConflictDialogData {
|
): ConflictDialogData {
|
||||||
val parentFile = rightFile?.remotePath?.let { File(it).parentFile }
|
val parentFile = File(rightFile.remotePath).parentFile
|
||||||
val folderName = if (parentFile != null) {
|
val folderName = if (parentFile != null) {
|
||||||
String.format(context.getString(R.string.in_folder), parentFile.absolutePath)
|
String.format(context.getString(R.string.in_folder), parentFile.absolutePath)
|
||||||
} else {
|
} else {
|
||||||
|
@ -371,8 +381,8 @@ class ConflictsResolveDialog : DialogFragment(), Injectable {
|
||||||
val leftCheckBoxData = ConflictFileData(leftTitle, leftTimestamp.toString(), leftFileSize)
|
val leftCheckBoxData = ConflictFileData(leftTitle, leftTimestamp.toString(), leftFileSize)
|
||||||
|
|
||||||
val rightTitle = context.getString(R.string.conflict_server_file)
|
val rightTitle = context.getString(R.string.conflict_server_file)
|
||||||
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile?.modificationTimestamp ?: 0)
|
val rightTimestamp = DisplayUtils.getRelativeTimestamp(context, rightFile.modificationTimestamp)
|
||||||
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile?.fileLength ?: 0)
|
val rightFileSize = DisplayUtils.bytesToHumanReadable(rightFile.fileLength)
|
||||||
val rightCheckBoxData = ConflictFileData(rightTitle, rightTimestamp.toString(), rightFileSize)
|
val rightCheckBoxData = ConflictFileData(rightTitle, rightTimestamp.toString(), rightFileSize)
|
||||||
|
|
||||||
val title = context.getString(R.string.choose_which_file)
|
val title = context.getString(R.string.choose_which_file)
|
||||||
|
|
|
@ -9,6 +9,7 @@ package com.owncloud.android.ui.dialog.parcel
|
||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import com.nextcloud.utils.extensions.readParcelableCompat
|
||||||
|
|
||||||
data class ConflictDialogData(
|
data class ConflictDialogData(
|
||||||
val folderName: String?,
|
val folderName: String?,
|
||||||
|
@ -66,12 +67,3 @@ data class ConflictFileData(
|
||||||
override fun newArray(size: Int): Array<ConflictFileData?> = arrayOfNulls(size)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue