mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-16 10:56:50 -04:00
#1023 Selected files get unselected on screen rotation - store boolean indicating action mode state in out bundle
This commit is contained in:
parent
51e90dd9c2
commit
52c642232f
@ -57,6 +57,7 @@ import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.Re
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestOpen
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestSelect
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestShareMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RestartActionMode
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.FileSelectListState
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.DeleteFiles
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.None
|
||||
@ -93,6 +94,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
object RequestDeleteMultiSelection : FileSelectActions()
|
||||
object RequestShareMultiSelection : FileSelectActions()
|
||||
object MultiModeFinished : FileSelectActions()
|
||||
object RestartActionMode : FileSelectActions()
|
||||
}
|
||||
|
||||
val sideEffects = PublishProcessor.create<SideEffect<out Any?>>()
|
||||
@ -150,6 +152,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
RequestShareMultiSelection -> ShareFiles(selectionsFromState())
|
||||
MultiModeFinished -> noSideEffectAndClearSelectionState()
|
||||
is RequestSelect -> noSideEffectSelectBook(it.bookOnDisk)
|
||||
RestartActionMode -> StartMultiSelection(fileSelectActions)
|
||||
}
|
||||
)
|
||||
}, Throwable::printStackTrace)
|
||||
@ -165,7 +168,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
)
|
||||
)
|
||||
}
|
||||
return StartMultiSelection(bookOnDisk, fileSelectActions)
|
||||
return StartMultiSelection(fileSelectActions)
|
||||
}
|
||||
|
||||
private fun selectBook(
|
||||
@ -181,10 +184,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
private fun noSideEffectSelectBook(bookOnDisk: BookOnDisk): SideEffect<Unit> {
|
||||
fileSelectListStates.value?.let {
|
||||
fileSelectListStates.postValue(
|
||||
it.copy(bookOnDiskListItems = it.bookOnDiskListItems.map { listItem ->
|
||||
if (listItem.id == bookOnDisk.id) listItem.apply { isSelected = !isSelected }
|
||||
else listItem
|
||||
})
|
||||
it.copy(bookOnDiskListItems = selectBook(it, bookOnDisk))
|
||||
)
|
||||
}
|
||||
return None
|
||||
|
@ -23,11 +23,11 @@ import android.content.pm.PackageManager
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Build.VERSION_CODES
|
||||
import android.os.Bundle
|
||||
import android.view.ActionMode
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
@ -56,6 +56,8 @@ import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.Re
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestSelect
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val WAS_IN_ACTION_MODE = "WAS_IN_ACTION_MODE"
|
||||
|
||||
class ZimFileSelectFragment : BaseFragment() {
|
||||
|
||||
@Inject lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
||||
@ -108,6 +110,9 @@ class ZimFileSelectFragment : BaseFragment() {
|
||||
zimManageViewModel.deviceListIsRefreshing.observe(this, Observer {
|
||||
zim_swiperefresh.isRefreshing = it!!
|
||||
})
|
||||
if (savedInstanceState != null && savedInstanceState.getBoolean(WAS_IN_ACTION_MODE)) {
|
||||
zimManageViewModel.fileSelectActions.offer(FileSelectActions.RestartActionMode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sideEffects() = zimManageViewModel.sideEffects.subscribe(
|
||||
@ -132,6 +137,11 @@ class ZimFileSelectFragment : BaseFragment() {
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putBoolean(WAS_IN_ACTION_MODE, actionMode != null)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
disposable.clear()
|
||||
|
@ -31,7 +31,7 @@ import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDis
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageActivity
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeleteFiles(private val booksOnDiskListItem: List<BookOnDisk>) :
|
||||
data class DeleteFiles(private val booksOnDiskListItem: List<BookOnDisk>) :
|
||||
SideEffect<Unit> {
|
||||
|
||||
@Inject lateinit var dialogShower: DialogShower
|
||||
|
@ -26,7 +26,7 @@ import org.kiwix.kiwixmobile.core.extensions.toast
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||
|
||||
class OpenFile(private val bookOnDisk: BookOnDisk) :
|
||||
data class OpenFile(private val bookOnDisk: BookOnDisk) :
|
||||
SideEffect<Unit> {
|
||||
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
|
@ -27,7 +27,7 @@ import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
|
||||
class ShareFiles(private val selectedBooks: List<BookOnDisk>) :
|
||||
data class ShareFiles(private val selectedBooks: List<BookOnDisk>) :
|
||||
SideEffect<Unit> {
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
val selectedFileShareIntent = Intent()
|
||||
|
@ -24,21 +24,20 @@ import io.reactivex.processors.PublishProcessor
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.startActionMode
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.MultiModeFinished
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestDeleteMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestShareMultiSelection
|
||||
|
||||
data class StartMultiSelection(
|
||||
val bookOnDisk: BooksOnDiskListItem.BookOnDisk,
|
||||
val fileSelectActions: PublishProcessor<FileSelectActions>
|
||||
) : SideEffect<ActionMode?> {
|
||||
override fun invokeWith(activity: AppCompatActivity) =
|
||||
override fun invokeWith(activity: AppCompatActivity): ActionMode? =
|
||||
activity.startActionMode(
|
||||
R.menu.menu_zim_files_contextual,
|
||||
mapOf(
|
||||
R.id.zim_file_delete_item to { fileSelectActions.offer(RequestDeleteMultiSelection) },
|
||||
R.id.zim_file_share_item to { fileSelectActions.offer(RequestShareMultiSelection) }
|
||||
)
|
||||
) { fileSelectActions.offer(FileSelectActions.MultiModeFinished) }
|
||||
) { fileSelectActions.offer(MultiModeFinished) }
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
||||
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book
|
||||
import org.kiwix.kiwixmobile.core.utils.BookUtils
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.SelectionMode.MULTI
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.SelectionMode.NORMAL
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState
|
||||
@ -51,7 +53,19 @@ import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CanWrite4G
|
||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CannotWrite4GbFile
|
||||
import org.kiwix.kiwixmobile.zim_manager.NetworkState.CONNECTED
|
||||
import org.kiwix.kiwixmobile.zim_manager.NetworkState.NOT_CONNECTED
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.MultiModeFinished
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestDeleteMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestOpen
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestSelect
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestShareMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RestartActionMode
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.FileSelectListState
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.DeleteFiles
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.None
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.OpenFile
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.ShareFiles
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.StartMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem
|
||||
import org.kiwix.sharedFunctions.InstantExecutorExtension
|
||||
import org.kiwix.sharedFunctions.book
|
||||
@ -406,4 +420,101 @@ class ZimManageViewModelTest {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SideEffects {
|
||||
@Test
|
||||
fun `RequestOpen offers OpenFile`() {
|
||||
val bookOnDisk = bookOnDisk()
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(RequestOpen(bookOnDisk)) }
|
||||
.assertValues(OpenFile(bookOnDisk))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `RequestMultiSelection offers StartMultiSelection and selects a book`() {
|
||||
val bookToSelect = bookOnDisk(databaseId = 0L)
|
||||
val unSelectedBook = bookOnDisk(databaseId = 1L)
|
||||
viewModel.fileSelectListStates.value = FileSelectListState(
|
||||
listOf(
|
||||
bookToSelect,
|
||||
unSelectedBook
|
||||
),
|
||||
NORMAL
|
||||
)
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(RequestMultiSelection(bookToSelect)) }
|
||||
.assertValues(StartMultiSelection(viewModel.fileSelectActions))
|
||||
viewModel.fileSelectListStates.test()
|
||||
.assertValue(
|
||||
FileSelectListState(
|
||||
listOf(bookToSelect.apply { isSelected = !isSelected }, unSelectedBook),
|
||||
MULTI
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `RequestDeleteMultiSelection offers DeleteFiles with selected books`() {
|
||||
val selectedBook = bookOnDisk().apply { isSelected = true }
|
||||
viewModel.fileSelectListStates.value =
|
||||
FileSelectListState(listOf(selectedBook, bookOnDisk()), NORMAL)
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(RequestDeleteMultiSelection) }
|
||||
.assertValues(DeleteFiles(listOf(selectedBook)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `RequestShareMultiSelection offers ShareFiles with selected books`() {
|
||||
val selectedBook = bookOnDisk().apply { isSelected = true }
|
||||
viewModel.fileSelectListStates.value =
|
||||
FileSelectListState(listOf(selectedBook, bookOnDisk()), NORMAL)
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(RequestShareMultiSelection) }
|
||||
.assertValues(ShareFiles(listOf(selectedBook)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `MultiModeFinished offers None`() {
|
||||
val selectedBook = bookOnDisk().apply { isSelected = true }
|
||||
viewModel.fileSelectListStates.value =
|
||||
FileSelectListState(listOf(selectedBook, bookOnDisk()), NORMAL)
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(MultiModeFinished) }
|
||||
.assertValues(None)
|
||||
viewModel.fileSelectListStates.test().assertValue(
|
||||
FileSelectListState(
|
||||
listOf(
|
||||
selectedBook.apply { isSelected = false },
|
||||
bookOnDisk()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `RequestSelect offers None and inverts selection`() {
|
||||
val selectedBook = bookOnDisk(0L).apply { isSelected = true }
|
||||
viewModel.fileSelectListStates.value =
|
||||
FileSelectListState(listOf(selectedBook, bookOnDisk(1L)), NORMAL)
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(RequestSelect(selectedBook)) }
|
||||
.assertValues(None)
|
||||
viewModel.fileSelectListStates.test().assertValue(
|
||||
FileSelectListState(
|
||||
listOf(
|
||||
selectedBook.apply { isSelected = false },
|
||||
bookOnDisk(1L)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `RestartActionMode offers StartMultiSelection`() {
|
||||
viewModel.sideEffects.test()
|
||||
.also { viewModel.fileSelectActions.offer(RestartActionMode) }
|
||||
.assertValues(StartMultiSelection(viewModel.fileSelectActions))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,28 +38,19 @@ object ActivityExtensions {
|
||||
onDestroyAction: () -> Unit
|
||||
): ActionMode? {
|
||||
return startSupportActionMode(object : ActionMode.Callback {
|
||||
override fun onActionItemClicked(
|
||||
mode: ActionMode,
|
||||
item: MenuItem
|
||||
) = idsToClickActions[item.itemId]?.let {
|
||||
it()
|
||||
mode.finish()
|
||||
true
|
||||
} ?: false
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem) =
|
||||
idsToClickActions[item.itemId]?.let {
|
||||
it()
|
||||
mode.finish()
|
||||
true
|
||||
} ?: false
|
||||
|
||||
override fun onCreateActionMode(
|
||||
mode: ActionMode,
|
||||
menu: Menu?
|
||||
): Boolean {
|
||||
mode.menuInflater
|
||||
.inflate(menuId, menu)
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
||||
mode.menuInflater.inflate(menuId, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(
|
||||
mode: ActionMode?,
|
||||
menu: Menu?
|
||||
) = false
|
||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
onDestroyAction()
|
||||
|
Loading…
x
Reference in New Issue
Block a user