Skip to content

Commit

Permalink
Add verification for moving/copying messages
Browse files Browse the repository at this point in the history
Added verification for moving messages into other folders (in response to Issue thunderbird#823)
- Currently, users can move messages into local-only folders which don't exist server-side, may end up with messages stuck in these local folders and effectively lost
- When online, refresh the folder list prior to moving; prevent messages ending up in "dead" unsynced folders which do not exist server-side
- When offline, provide the user with a warning saying that "ThunderBird is not connected to the Internet. Any changes you make now may not be synced properly."
    - Users may proceed anyways, cancel the move/copy/draft/archive/spam operation, or "don't show again" and always proceed anyways
  • Loading branch information
dnicules authored Dec 9, 2024
1 parent fc36dfe commit 4209134
Showing 1 changed file with 183 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.view.ActionMode
import androidx.core.os.BundleCompat
import androidx.core.os.bundleOf
Expand Down Expand Up @@ -46,6 +47,7 @@ import com.fsck.k9.helper.Utility
import com.fsck.k9.helper.mapToSet
import com.fsck.k9.mail.Flag
import com.fsck.k9.mail.MessagingException
import com.fsck.k9.network.ConnectivityManager
import com.fsck.k9.search.getAccounts
import com.fsck.k9.ui.R
import com.fsck.k9.ui.changelog.RecentChangesActivity
Expand Down Expand Up @@ -82,6 +84,7 @@ class MessageListFragment :
private val messagingController: MessagingController by inject()
private val accountManager: AccountManager by inject()
private val clock: Clock by inject()
private val connectivityManager: ConnectivityManager by inject()

private val handler = MessageListHandler(this)
private val activityListener = MessageListActivityListener()
Expand Down Expand Up @@ -1035,11 +1038,47 @@ class MessageListFragment :
computeBatchDirection()
}

private fun onMove(message: MessageReference) {
onMove(listOf(message))
private interface ConnectivityDialogCallback {
fun onDialogResult(result: Int)
}

private fun onMove(messages: List<MessageReference>) {
private fun showConnectivityDialog(callback: ConnectivityDialogCallback) { // added
val sharedPreferences = context?.getSharedPreferences("app_preferences", Context.MODE_PRIVATE);
val dontShowAgain = sharedPreferences?.getBoolean("dont_show_connectivity_warning", false) ?: false;
//sharedPreferences?.edit()?.putBoolean("dont_show_connectivity_warning", false)?.apply()

//callback.onDialogResult(0);
if (dontShowAgain) {
// Proceed directly if "Don't show again" is checked
callback.onDialogResult(1);
return;
}
//callback.onDialogResult(0);
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("No Internet Connection")
.setMessage("ThunderBird is not connected to the Internet. Any changes you make now may not be synced properly.")
.setPositiveButton("Proceed") { _, _ ->
callback.onDialogResult(1);

//Log.d("onMove", "User chose to proceed")
}
.setNegativeButton("Cancel") { _, _ ->
callback.onDialogResult(-1);

//Log.d("onMove", "User chose to cancel")
}
.setNeutralButton("Don't show again") { _, _ ->
// Save the preference to not show the dialog again
callback.onDialogResult(1);
sharedPreferences?.edit()?.putBoolean("dont_show_connectivity_warning", true)?.apply()
//Log.d("onMove", "User chose 'Don't show again'")
}
.show()

//return;
}

private fun proceedWithMove(messages: List<MessageReference>) {
if (!checkCopyOrMovePossible(messages, FolderOperation.MOVE)) return

val folderId = when {
Expand All @@ -1058,11 +1097,32 @@ class MessageListFragment :
)
}

private fun onCopy(message: MessageReference) {
onCopy(listOf(message))
private fun onMove(message: MessageReference) {
onMove(listOf(message))
}

private fun onCopy(messages: List<MessageReference>) {
private fun onMove(messages: List<MessageReference>) {

if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
proceedWithMove(messages);
return;
}
}
},
)
} else {
proceedWithMove(messages);
return;
}
}

private fun proceedWithCopy(messages: List<MessageReference>) {
if (!checkCopyOrMovePossible(messages, FolderOperation.COPY)) return

val folderId = when {
Expand All @@ -1081,6 +1141,30 @@ class MessageListFragment :
)
}

private fun onCopy(message: MessageReference) {
onCopy(listOf(message))
}

private fun onCopy(messages: List<MessageReference>) {
if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
proceedWithCopy(messages);
return;
}
}
},
)
} else {
proceedWithCopy(messages);
return;
}
}

private fun displayFolderChoice(
operation: FolderOperation,
requestCode: Int,
Expand Down Expand Up @@ -1172,11 +1256,43 @@ class MessageListFragment :
}

private fun copy(messages: List<MessageReference>, folderId: Long) {
copyOrMove(messages, folderId, FolderOperation.COPY)
if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
copyOrMove(messages, folderId, FolderOperation.COPY)
return;
}
}
},
)
} else {
copyOrMove(messages, folderId, FolderOperation.COPY);
return;
}
}

private fun move(messages: List<MessageReference>, folderId: Long) {
copyOrMove(messages, folderId, FolderOperation.MOVE)
if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
copyOrMove(messages, folderId, FolderOperation.MOVE)
return;
}
}
},
)
} else {
copyOrMove(messages, folderId, FolderOperation.MOVE);
return;
}
}

private fun copyOrMove(messages: List<MessageReference>, destinationFolderId: Long, operation: FolderOperation) {
Expand Down Expand Up @@ -1206,8 +1322,25 @@ class MessageListFragment :
}

private fun onMoveToDraftsFolder(messages: List<MessageReference>) {
messagingController.moveToDraftsFolder(account, currentFolder!!.databaseId, messages)
activeMessages = null
if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
messagingController.moveToDraftsFolder(account, currentFolder!!.databaseId, messages)
activeMessages = null
return;
}
}
},
)
} else {
messagingController.moveToDraftsFolder(account, currentFolder!!.databaseId, messages)
activeMessages = null
return;
}
}

override fun doPositiveClick(dialogId: Int) {
Expand Down Expand Up @@ -1354,8 +1487,26 @@ class MessageListFragment :
}

fun onMove() {
selectedMessage?.let { message ->
onMove(message)
if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
selectedMessage?.let { message ->
onMove(message)
}
return;
}
}
},
)
} else {
selectedMessage?.let { message ->
onMove(message)
}
return;
}
}

Expand All @@ -1366,8 +1517,26 @@ class MessageListFragment :
}

fun onCopy() {
selectedMessage?.let { message ->
onCopy(message)
if (!preMove()) {
showConnectivityDialog(
object : ConnectivityDialogCallback {
override fun onDialogResult(result: Int) {
if (result == -1) {
return
} else if (result == 1) {
selectedMessage?.let { message ->
onCopy(message)
}
return;
}
}
},
)
} else {
selectedMessage?.let { message ->
onCopy(message)
}
return;
}
}

Expand Down

0 comments on commit 4209134

Please sign in to comment.