Repository: thundernest/k-9
Issue: Crash when message is removed while being swiped

### Checklist

- [X] I have used the search function to see if someone else has already submitted the same bug report.
- [X] I will describe the problem with as much detail as possible.

### App version

6.503

### Where did you get the app from?

None

### Android version

doesn't matter

### Device model

_No response_

### Steps to reproduce

1. Set up an IMAP account with Push enabled
2. Drag a message list item to the side and keep holding it
3. Delete that message using another client and wait until the change is synced to K-9 Mail

### Expected behavior

The message list item disappears.

### Actual behavior

Crash

### Logs

```text
Exception java.lang.IllegalStateException:
  at com.fsck.k9.ui.messagelist.MessageListSwipeCallback.getMessageListItem (MessageListSwipeCallback.kt:235)
  at com.fsck.k9.ui.messagelist.MessageListSwipeCallback.onSwipeEnded (MessageListSwipeCallback.kt:105)
  at app.k9mail.ui.utils.itemtouchhelper.ItemTouchHelper$MoveBackAnimation.onAnimationEnd (ItemTouchHelper.java:2591)
  at android.animation.Animator$AnimatorListener.onAnimationEnd (Animator.java:600)
  at android.animation.ValueAnimator.endAnimation (ValueAnimator.java:1333)
  at android.animation.ValueAnimator.doAnimationFrame (ValueAnimator.java:1575)
  at android.animation.AnimationHandler.doAnimationFrame (AnimationHandler.java:307)
  at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame
  at android.animation.AnimationHandler$1.doFrame (AnimationHandler.java:86)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1229)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1239)
  at android.view.Choreographer.doCallbacks (Choreographer.java:899)
  at android.view.Choreographer.doFrame (Choreographer.java:827)
  at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1214)
  at android.os.Handler.handleCallback (Handler.java:942)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:201)
  at android.os.Looper.loop (Looper.java:288)
  at android.app.ActivityThread.main (ActivityThread.java:7872)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)
```

Changed files:
app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListSwipeCallback.kt

diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListSwipeCallback.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListSwipeCallback.kt
index 6077ccff1..9c2311284 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListSwipeCallback.kt
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListSwipeCallback.kt
@@ -69,6 +69,8 @@ class MessageListSwipeCallback(
     }
 
     override fun onSwipeStarted(viewHolder: ViewHolder, direction: Int) {
+        val item = viewHolder.messageListItem ?: return
+
         // Mark view to prevent MessageListItemAnimator from interfering with swipe animations
         viewHolder.markAsSwiped(true)
 
@@ -78,21 +80,23 @@ class MessageListSwipeCallback(
             else -> error("Unsupported direction: $direction")
         }
 
-        listener.onSwipeStarted(viewHolder.messageListItem, swipeAction)
+        listener.onSwipeStarted(item, swipeAction)
     }
 
     override fun onSwipeDirectionChanged(viewHolder: ViewHolder, direction: Int) {
+        val item = viewHolder.messageListItem ?: return
+
         val swipeAction = when (direction) {
             ItemTouchHelper.RIGHT -> swipeRightAction
             ItemTouchHelper.LEFT -> swipeLeftAction
             else -> error("Unsupported direction: $direction")
         }
 
-        listener.onSwipeActionChanged(viewHolder.messageListItem, swipeAction)
+        listener.onSwipeActionChanged(item, swipeAction)
     }
 
     override fun onSwiped(viewHolder: ViewHolder, direction: Int) {
-        val item = viewHolder.messageListItem
+        val item = viewHolder.messageListItem ?: return
 
         when (direction) {
             ItemTouchHelper.RIGHT -> listener.onSwipeAction(item, swipeRightAction)
@@ -102,7 +106,9 @@ class MessageListSwipeCallback(
     }
 
     override fun onSwipeEnded(viewHolder: ViewHolder) {
-        listener.onSwipeEnded(viewHolder.messageListItem)
+        val item = viewHolder.messageListItem ?: return
+
+        listener.onSwipeEnded(item)
     }
 
     override fun clearView(recyclerView: RecyclerView, viewHolder: ViewHolder) {
@@ -230,9 +236,8 @@ class MessageListSwipeCallback(
         return (super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy) * percentage).toLong()
     }
 
-    private val ViewHolder.messageListItem: MessageListItem
+    private val ViewHolder.messageListItem: MessageListItem?
         get() = (this as? MessageViewHolder)?.uniqueId?.let { adapter.getItemById(it) }
-            ?: error("Couldn't find MessageListItem")
 }
 
 fun interface SwipeActionSupportProvider {