diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 3948536834..9d6640d9fa 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -4,6 +4,8 @@ * Bug Fixes: * Fix OPML import. + * Fix podcasts and folders rearrange crash. + ([#200](https://github.com/Automattic/pocket-casts-android/issues/200)). ### 7.20.1 diff --git a/dependencies.gradle b/dependencies.gradle index b92c1de0cf..9aa7f4da5d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -26,7 +26,7 @@ project.ext { applicationId = 'au.com.shiftyjelly.pocketcasts' versionCode = getVersionCode() - versionName = '7.20.1' + getVersionNameSuffix() + versionName = '7.20.2' + getVersionNameSuffix() // Android minSdkVersion = 23 diff --git a/modules/features/podcasts/src/main/java/au/com/shiftyjelly/pocketcasts/podcasts/viewmodel/PodcastsViewModel.kt b/modules/features/podcasts/src/main/java/au/com/shiftyjelly/pocketcasts/podcasts/viewmodel/PodcastsViewModel.kt index 4301737ead..a948d07e58 100644 --- a/modules/features/podcasts/src/main/java/au/com/shiftyjelly/pocketcasts/podcasts/viewmodel/PodcastsViewModel.kt +++ b/modules/features/podcasts/src/main/java/au/com/shiftyjelly/pocketcasts/podcasts/viewmodel/PodcastsViewModel.kt @@ -23,6 +23,7 @@ import io.reactivex.rxkotlin.Observables import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import timber.log.Timber import java.util.Collections import java.util.Optional import javax.inject.Inject @@ -179,24 +180,30 @@ class PodcastsViewModel val refreshObservable: LiveData = LiveDataReactiveStreams.fromPublisher(settings.refreshStateObservable.toFlowable(BackpressureStrategy.LATEST)) - var adapterState: MutableList = mutableListOf() + private var adapterState: MutableList = mutableListOf() + /** * User rearranges the grid with a drag */ fun moveFolderItem(fromPosition: Int, toPosition: Int): List { - if (adapterState.isEmpty() || toPosition >= adapterState.size) { + if (adapterState.isEmpty()) { return adapterState } - if (fromPosition < toPosition) { - for (index in fromPosition until toPosition) { - Collections.swap(adapterState, index, index + 1) - } - } else { - for (index in fromPosition downTo toPosition + 1) { - Collections.swap(adapterState, index, index - 1) + try { + if (fromPosition < toPosition) { + for (index in fromPosition until toPosition) { + Collections.swap(adapterState, index, index + 1) + } + } else { + for (index in fromPosition downTo toPosition + 1) { + Collections.swap(adapterState, index, index - 1) + } } + } catch (ex: IndexOutOfBoundsException) { + Timber.e("Move folder item failed.", ex) } + return adapterState.toList() } diff --git a/modules/services/views/src/main/java/au/com/shiftyjelly/pocketcasts/views/adapter/PodcastTouchCallback.kt b/modules/services/views/src/main/java/au/com/shiftyjelly/pocketcasts/views/adapter/PodcastTouchCallback.kt index 098bcb1177..36b7de7687 100644 --- a/modules/services/views/src/main/java/au/com/shiftyjelly/pocketcasts/views/adapter/PodcastTouchCallback.kt +++ b/modules/services/views/src/main/java/au/com/shiftyjelly/pocketcasts/views/adapter/PodcastTouchCallback.kt @@ -2,6 +2,7 @@ package au.com.shiftyjelly.pocketcasts.views.adapter import android.content.Context import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView class PodcastTouchCallback(val adapter: ItemTouchHelperAdapter, val context: Context) : ItemTouchHelper.Callback() { @@ -17,22 +18,28 @@ class PodcastTouchCallback(val adapter: ItemTouchHelperAdapter, val context: Con fun onItemClear() } - override fun getMovementFlags(recyclerView: androidx.recyclerview.widget.RecyclerView, viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder): Int { + override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int { val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.START or ItemTouchHelper.END val swipeFlags = 0 return ItemTouchHelper.SimpleCallback.makeMovementFlags(dragFlags, swipeFlags) } - override fun onMove(recyclerView: androidx.recyclerview.widget.RecyclerView, viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder, target: androidx.recyclerview.widget.RecyclerView.ViewHolder): Boolean { - adapter.onPodcastMove(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition) + override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { + val position = viewHolder.bindingAdapterPosition + val targetPosition = target.bindingAdapterPosition + if (position == RecyclerView.NO_POSITION || targetPosition == RecyclerView.NO_POSITION) { + return false + } + + adapter.onPodcastMove(position, targetPosition) isMoving = true return true } - override fun onSwiped(viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder, direction: Int) { + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { } - override fun onSelectedChanged(viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder?, actionState: Int) { + override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { if (viewHolder is ItemTouchHelperViewHolder) { when (actionState) { ItemTouchHelper.ACTION_STATE_DRAG -> viewHolder.onItemDrag() @@ -42,7 +49,7 @@ class PodcastTouchCallback(val adapter: ItemTouchHelperAdapter, val context: Con super.onSelectedChanged(viewHolder, actionState) } - override fun clearView(recyclerView: androidx.recyclerview.widget.RecyclerView, viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder) { + override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { super.clearView(recyclerView, viewHolder) if (viewHolder is ItemTouchHelperViewHolder) {