mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-22 03:54:18 -04:00
#1253 readd action mode for sharing and deleting zim files on disk
This commit is contained in:
parent
62987fa4ed
commit
51998e8f20
@ -218,7 +218,7 @@
|
||||
},
|
||||
{
|
||||
"id": "2:6862771806221961183",
|
||||
"name": "zimID"
|
||||
"name": "zimId"
|
||||
},
|
||||
{
|
||||
"id": "3:4312769031500860715",
|
||||
|
@ -23,6 +23,7 @@ import dagger.Subcomponent
|
||||
import org.kiwix.kiwixmobile.di.modules.ActivityModule
|
||||
import org.kiwix.kiwixmobile.downloader.DownloadFragment
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.ZimFileSelectFragment
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.DeleteFiles
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.LibraryFragment
|
||||
|
||||
@Subcomponent(modules = [ActivityModule::class])
|
||||
@ -33,6 +34,8 @@ interface ActivityComponent {
|
||||
|
||||
fun inject(zimFileSelectFragment: ZimFileSelectFragment)
|
||||
|
||||
fun inject(deleteFiles: DeleteFiles)
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
package org.kiwix.kiwixmobile.extensions
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.ActionMode
|
||||
import android.view.ActionMode.Callback
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
|
||||
fun Activity.startActionMode(
|
||||
menuId: Int,
|
||||
idsToClickActions: Map<Int, () -> Any>,
|
||||
onDestroyAction: () -> Unit
|
||||
): ActionMode? {
|
||||
return startActionMode(object : Callback {
|
||||
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.getMenuInflater()
|
||||
.inflate(menuId, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(
|
||||
mode: ActionMode?,
|
||||
menu: Menu?
|
||||
) = false
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
onDestroyAction()
|
||||
}
|
||||
|
||||
})
|
||||
}
|
@ -37,7 +37,6 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.text.SpannableString;
|
||||
@ -100,11 +99,9 @@ import org.kiwix.kiwixmobile.base.BaseActivity;
|
||||
import org.kiwix.kiwixmobile.bookmark.BookmarkItem;
|
||||
import org.kiwix.kiwixmobile.bookmark.BookmarksActivity;
|
||||
import org.kiwix.kiwixmobile.data.ZimContentProvider;
|
||||
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
|
||||
import org.kiwix.kiwixmobile.help.HelpActivity;
|
||||
import org.kiwix.kiwixmobile.history.HistoryActivity;
|
||||
import org.kiwix.kiwixmobile.history.HistoryListItem;
|
||||
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity;
|
||||
import org.kiwix.kiwixmobile.search.SearchActivity;
|
||||
import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity;
|
||||
import org.kiwix.kiwixmobile.utils.DimenUtils;
|
||||
@ -377,6 +374,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback,
|
||||
open(bookOnDiskItem);
|
||||
return Unit.INSTANCE;
|
||||
},
|
||||
null,
|
||||
null),
|
||||
BookOnDiskDelegate.LanguageDelegate.INSTANCE
|
||||
);
|
||||
@ -2105,7 +2103,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback,
|
||||
|
||||
@Override
|
||||
public void addBooks(List<BooksOnDiskListItem> books) {
|
||||
booksAdapter.setItemList(books);
|
||||
booksAdapter.setItems(books);
|
||||
}
|
||||
|
||||
private void searchFiles() {
|
||||
|
@ -52,9 +52,24 @@ import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CanWrite4G
|
||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.CannotWrite4GbFile
|
||||
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState.NotEnoughSpaceFor4GbFile
|
||||
import org.kiwix.kiwixmobile.zim_manager.NetworkState.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.fileselect_view.FileSelectListState
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode.MULTI
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode.NORMAL
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.StorageObserver
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
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.SideEffect
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.StartMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.BookItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.DividerItem
|
||||
@ -79,16 +94,26 @@ class ZimManageViewModel @Inject constructor(
|
||||
private val defaultLanguageProvider: DefaultLanguageProvider,
|
||||
private val dataSource: DataSource
|
||||
) : ViewModel() {
|
||||
sealed class FileSelectActions {
|
||||
data class RequestOpen(val bookOnDisk: BookOnDisk) : FileSelectActions()
|
||||
data class RequestSelect(val bookOnDisk: BookOnDisk) : FileSelectActions()
|
||||
data class RequestMultiSelection(val bookOnDisk: BookOnDisk) : FileSelectActions()
|
||||
object RequestDeleteMultiSelection : FileSelectActions()
|
||||
object RequestShareMultiSelection : FileSelectActions()
|
||||
object MultiModeFinished : FileSelectActions()
|
||||
}
|
||||
|
||||
val sideEffects = PublishProcessor.create<SideEffect<out Any?>>()
|
||||
val libraryItems: MutableLiveData<List<LibraryListItem>> = MutableLiveData()
|
||||
val downloadItems: MutableLiveData<List<DownloadItem>> = MutableLiveData()
|
||||
val bookItems: MutableLiveData<List<BooksOnDiskListItem>> = MutableLiveData()
|
||||
val fileSelectListStates: MutableLiveData<FileSelectListState> = MutableLiveData()
|
||||
val deviceListIsRefreshing = MutableLiveData<Boolean>()
|
||||
val libraryListIsRefreshing = MutableLiveData<Boolean>()
|
||||
val networkStates = MutableLiveData<NetworkState>()
|
||||
val languageItems = MutableLiveData<List<Language>>()
|
||||
|
||||
val requestFileSystemCheck = PublishProcessor.create<Unit>()
|
||||
val fileSelectActions = PublishProcessor.create<FileSelectActions>()
|
||||
val requestDownloadLibrary = BehaviorProcessor.createDefault<Unit>(Unit)
|
||||
val requestFiltering = BehaviorProcessor.createDefault<String>("")
|
||||
val requestLanguagesDialog = PublishProcessor.create<Unit>()
|
||||
@ -127,10 +152,74 @@ class ZimManageViewModel @Inject constructor(
|
||||
updateLanguagesInDao(networkLibrary, languages),
|
||||
updateNetworkStates(),
|
||||
updateLanguageItemsForDialog(languages),
|
||||
requestsAndConnectivtyChangesToLibraryRequests(networkLibrary)
|
||||
requestsAndConnectivtyChangesToLibraryRequests(networkLibrary),
|
||||
fileSelectActions()
|
||||
)
|
||||
}
|
||||
|
||||
private fun fileSelectActions() = fileSelectActions.subscribe({
|
||||
sideEffects.offer(
|
||||
when (it) {
|
||||
is RequestOpen -> OpenFile(it.bookOnDisk)
|
||||
is RequestMultiSelection -> startMultiSelectionAndSelectBook(it.bookOnDisk)
|
||||
RequestDeleteMultiSelection -> DeleteFiles(selectionsFromState())
|
||||
RequestShareMultiSelection -> ShareFiles(selectionsFromState())
|
||||
MultiModeFinished -> noSideEffectAndClearSelectionState()
|
||||
is RequestSelect -> noSideEffectSelectBook(it.bookOnDisk)
|
||||
}
|
||||
)
|
||||
}, Throwable::printStackTrace)
|
||||
|
||||
private fun startMultiSelectionAndSelectBook(
|
||||
bookOnDisk: BookOnDisk
|
||||
): StartMultiSelection {
|
||||
fileSelectListStates.value?.let {
|
||||
fileSelectListStates.postValue(
|
||||
it.copy(
|
||||
bookOnDiskListItems = selectBook(it, bookOnDisk),
|
||||
selectionMode = MULTI
|
||||
)
|
||||
)
|
||||
}
|
||||
return StartMultiSelection(bookOnDisk, fileSelectActions)
|
||||
}
|
||||
|
||||
private fun selectBook(
|
||||
it: FileSelectListState,
|
||||
bookOnDisk: BookOnDisk
|
||||
): List<BooksOnDiskListItem> {
|
||||
return it.bookOnDiskListItems.map { listItem ->
|
||||
if (listItem.id == bookOnDisk.id) listItem.apply { isSelected = !isSelected }
|
||||
else listItem
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
)
|
||||
}
|
||||
return None
|
||||
}
|
||||
|
||||
private fun selectionsFromState() = fileSelectListStates.value?.selectedBooks ?: emptyList()
|
||||
|
||||
private fun noSideEffectAndClearSelectionState(): SideEffect<Unit> {
|
||||
fileSelectListStates.value?.let {
|
||||
fileSelectListStates.postValue(
|
||||
it.copy(
|
||||
bookOnDiskListItems = it.bookOnDiskListItems.map { it.apply { isSelected = false } },
|
||||
selectionMode = NORMAL
|
||||
)
|
||||
)
|
||||
}
|
||||
return None
|
||||
}
|
||||
|
||||
private fun requestsAndConnectivtyChangesToLibraryRequests(library: PublishProcessor<LibraryNetworkEntity>) =
|
||||
Flowable.combineLatest(
|
||||
requestDownloadLibrary,
|
||||
@ -411,10 +500,27 @@ class ZimManageViewModel @Inject constructor(
|
||||
private fun updateBookItems() =
|
||||
dataSource.booksOnDiskAsListItems()
|
||||
.subscribe(
|
||||
bookItems::postValue,
|
||||
{ newList ->
|
||||
fileSelectListStates.postValue(
|
||||
fileSelectListStates.value?.let { inheritSelections(it, newList) }
|
||||
?: FileSelectListState(newList)
|
||||
)
|
||||
},
|
||||
Throwable::printStackTrace
|
||||
)
|
||||
|
||||
private fun inheritSelections(
|
||||
oldState: FileSelectListState,
|
||||
newList: MutableList<BooksOnDiskListItem>
|
||||
): FileSelectListState {
|
||||
return oldState.copy(
|
||||
bookOnDiskListItems = newList.map { newBookOnDisk ->
|
||||
val firstOrNull =
|
||||
oldState.bookOnDiskListItems.firstOrNull { oldBookOnDisk -> oldBookOnDisk.id == newBookOnDisk.id }
|
||||
newBookOnDisk.apply { isSelected = firstOrNull?.isSelected ?: false }
|
||||
})
|
||||
}
|
||||
|
||||
private fun removeCompletedDownloadsFromDb(downloadStatuses: Flowable<List<DownloadStatus>>) =
|
||||
downloadStatuses
|
||||
.observeOn(Schedulers.io())
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (C) 2018 Kiwix <android.kiwix.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view
|
||||
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode.NORMAL
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
|
||||
data class FileSelectListState(
|
||||
val bookOnDiskListItems: List<BooksOnDiskListItem>,
|
||||
val selectionMode: SelectionMode = NORMAL
|
||||
) {
|
||||
val selectedBooks by lazy {
|
||||
bookOnDiskListItems.filter { it.isSelected }.filterIsInstance(BookOnDisk::class.java)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class SelectionMode {
|
||||
NORMAL,
|
||||
MULTI
|
||||
}
|
@ -21,8 +21,8 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.ActionMode
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -32,49 +32,49 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.zim_list.file_management_no_files
|
||||
import kotlinx.android.synthetic.main.zim_list.zim_swiperefresh
|
||||
import kotlinx.android.synthetic.main.zim_list.zimfilelist
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.R.string
|
||||
import org.kiwix.kiwixmobile.base.BaseFragment
|
||||
import org.kiwix.kiwixmobile.data.ZimContentProvider
|
||||
import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao
|
||||
import org.kiwix.kiwixmobile.di.components.ActivityComponent
|
||||
import org.kiwix.kiwixmobile.extensions.toast
|
||||
import org.kiwix.kiwixmobile.utils.BookUtils
|
||||
import org.kiwix.kiwixmobile.utils.Constants.REQUEST_STORAGE_PERMISSION
|
||||
import org.kiwix.kiwixmobile.utils.DialogShower
|
||||
import org.kiwix.kiwixmobile.utils.KiwixDialog.DeleteZim
|
||||
import org.kiwix.kiwixmobile.utils.LanguageUtils
|
||||
import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.utils.files.FileUtils
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageActivity
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions
|
||||
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.fileselect_view.adapter.BookOnDiskDelegate.BookDelegate
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BookOnDiskDelegate.LanguageDelegate
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskAdapter
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import javax.inject.Inject
|
||||
|
||||
class ZimFileSelectFragment : BaseFragment() {
|
||||
|
||||
@Inject lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
||||
@Inject lateinit var bookDao: NewBookDao
|
||||
@Inject lateinit var dialogShower: DialogShower
|
||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
@Inject lateinit var bookUtils: BookUtils
|
||||
|
||||
private var actionMode: ActionMode? = null
|
||||
val disposable = CompositeDisposable()
|
||||
|
||||
private val zimManageViewModel: ZimManageViewModel by lazy {
|
||||
ViewModelProviders.of(activity!!, viewModelFactory)
|
||||
.get(ZimManageViewModel::class.java)
|
||||
}
|
||||
|
||||
private val bookDelegate: BookDelegate by lazy {
|
||||
BookDelegate(sharedPreferenceUtil,
|
||||
{ offerAction(RequestOpen(it)) },
|
||||
{ offerAction(RequestMultiSelection(it)) },
|
||||
{ offerAction(RequestSelect(it)) })
|
||||
}
|
||||
|
||||
private val booksOnDiskAdapter: BooksOnDiskAdapter by lazy {
|
||||
BooksOnDiskAdapter(
|
||||
BookDelegate(sharedPreferenceUtil, this::openOnClick, this::deleteOnLongClick),
|
||||
LanguageDelegate
|
||||
)
|
||||
BooksOnDiskAdapter(bookDelegate, LanguageDelegate)
|
||||
}
|
||||
|
||||
override fun inject(activityComponent: ActivityComponent) {
|
||||
@ -101,31 +101,51 @@ class ZimFileSelectFragment : BaseFragment() {
|
||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
||||
setHasFixedSize(true)
|
||||
}
|
||||
zimManageViewModel.bookItems.observe(this, Observer {
|
||||
booksOnDiskAdapter.itemList = it!!
|
||||
checkEmpty(it)
|
||||
})
|
||||
zimManageViewModel.fileSelectListStates.observe(this, Observer { render(it) })
|
||||
disposable.add(sideEffects())
|
||||
zimManageViewModel.deviceListIsRefreshing.observe(this, Observer {
|
||||
zim_swiperefresh.isRefreshing = it!!
|
||||
})
|
||||
}
|
||||
|
||||
private fun sideEffects() = zimManageViewModel.sideEffects.subscribe(
|
||||
{
|
||||
val effectResult = it.invokeWith(activity!!)
|
||||
if (effectResult is ActionMode) {
|
||||
actionMode = effectResult
|
||||
}
|
||||
}, Throwable::printStackTrace
|
||||
)
|
||||
|
||||
private fun render(state: FileSelectListState) {
|
||||
val items = state.bookOnDiskListItems
|
||||
bookDelegate.selectionMode = state.selectionMode
|
||||
booksOnDiskAdapter.items = items
|
||||
actionMode?.title = String.format("%d", state.selectedBooks.size)
|
||||
file_management_no_files.visibility = if (items.isEmpty()) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
private fun checkEmpty(books: List<Any>) {
|
||||
file_management_no_files.visibility =
|
||||
if (books.isEmpty()) View.VISIBLE
|
||||
else View.GONE
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
private fun offerAction(
|
||||
action: FileSelectActions
|
||||
) {
|
||||
zimManageViewModel.fileSelectActions.offer(action)
|
||||
}
|
||||
|
||||
private fun checkPermissions() {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
activity!!,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
) != PackageManager.PERMISSION_GRANTED && Build.VERSION.SDK_INT > 18
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
context.toast(R.string.request_storage)
|
||||
requestPermissions(
|
||||
@ -140,34 +160,4 @@ class ZimFileSelectFragment : BaseFragment() {
|
||||
private fun requestFileSystemCheck() {
|
||||
zimManageViewModel.requestFileSystemCheck.onNext(Unit)
|
||||
}
|
||||
|
||||
private fun openOnClick(it: BookOnDisk) {
|
||||
val file = it.file
|
||||
ZimContentProvider.canIterate = false
|
||||
if (!file.canRead()) {
|
||||
context.toast(string.error_filenotfound)
|
||||
} else {
|
||||
(activity as ZimManageActivity).finishResult(file.path)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteOnLongClick(it: BookOnDisk) {
|
||||
dialogShower.show(DeleteZim, {
|
||||
if (deleteSpecificZimFile(it)) {
|
||||
context.toast(string.delete_specific_zim_toast)
|
||||
} else {
|
||||
context.toast(string.delete_zim_failed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun deleteSpecificZimFile(book: BookOnDisk): Boolean {
|
||||
val file = book.file
|
||||
FileUtils.deleteZimFile(file.path)
|
||||
if (file.exists()) {
|
||||
return false
|
||||
}
|
||||
bookDao.delete(book.databaseId!!)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,13 @@
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.extensions.inflate
|
||||
import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode.NORMAL
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BookOnDiskViewHolder.BookViewHolder
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BookOnDiskViewHolder.LanguageItemViewHolder
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.LanguageItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.base.AbsDelegateAdapter
|
||||
@ -33,17 +35,28 @@ sealed class BookOnDiskDelegate<I : BooksOnDiskListItem, VH : BookOnDiskViewHold
|
||||
class BookDelegate(
|
||||
val sharedPreferenceUtil: SharedPreferenceUtil,
|
||||
val clickAction: (BookOnDisk) -> Unit,
|
||||
val longClickAction: ((BookOnDisk) -> Unit)? = null
|
||||
val longClickAction: ((BookOnDisk) -> Unit)? = null,
|
||||
val multiSelectAction: ((BookOnDisk) -> Unit)? = null
|
||||
) : BookOnDiskDelegate<BookOnDisk, BookViewHolder>() {
|
||||
|
||||
override val itemClass = BookOnDisk::class.java
|
||||
|
||||
var selectionMode: SelectionMode = NORMAL
|
||||
|
||||
override fun bind(
|
||||
viewHolder: ViewHolder,
|
||||
itemToBind: BooksOnDiskListItem
|
||||
) {
|
||||
(viewHolder as BookOnDiskViewHolder.BookViewHolder).bind((itemToBind as BookOnDisk), selectionMode)
|
||||
}
|
||||
|
||||
override fun createViewHolder(parent: ViewGroup) =
|
||||
BookViewHolder(
|
||||
parent.inflate(R.layout.item_book, false),
|
||||
sharedPreferenceUtil,
|
||||
clickAction,
|
||||
longClickAction
|
||||
longClickAction,
|
||||
multiSelectAction
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter
|
||||
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.base.AdapterDelegate
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.base.AdapterDelegateManager
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.base.BaseDelegateAdapter
|
||||
|
||||
class BooksOnDiskAdapter(
|
||||
|
@ -6,6 +6,7 @@ import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
sealed class BooksOnDiskListItem {
|
||||
var isSelected: Boolean = false
|
||||
abstract val id: Long
|
||||
|
||||
data class LanguageItem constructor(
|
||||
|
@ -3,6 +3,7 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter
|
||||
import android.graphics.ColorMatrixColorFilter
|
||||
import android.view.View
|
||||
import kotlinx.android.synthetic.main.header_language.header_language
|
||||
import kotlinx.android.synthetic.main.item_book.itemBookCheckbox
|
||||
import kotlinx.android.synthetic.main.item_book.item_book_article_count
|
||||
import kotlinx.android.synthetic.main.item_book.item_book_date
|
||||
import kotlinx.android.synthetic.main.item_book.item_book_description
|
||||
@ -17,6 +18,9 @@ import org.kiwix.kiwixmobile.main.KiwixWebView
|
||||
import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.zim_manager.KiloByte
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.ArticleCount
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode.MULTI
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.SelectionMode.NORMAL
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.LanguageItem
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.base.BaseViewHolder
|
||||
@ -28,10 +32,17 @@ sealed class BookOnDiskViewHolder<T : BooksOnDiskListItem>(containerView: View)
|
||||
containerView: View,
|
||||
private val sharedPreferenceUtil: SharedPreferenceUtil,
|
||||
private val clickAction: (BookOnDisk) -> Unit,
|
||||
private val longClickAction: ((BookOnDisk) -> Unit)?
|
||||
private val longClickAction: ((BookOnDisk) -> Unit)?,
|
||||
private val multiSelectAction: ((BookOnDisk) -> Unit)?
|
||||
) : BookOnDiskViewHolder<BookOnDisk>(containerView) {
|
||||
|
||||
override fun bind(item: BookOnDisk) {
|
||||
}
|
||||
|
||||
fun bind(
|
||||
item: BookOnDisk,
|
||||
selectionMode: SelectionMode
|
||||
) {
|
||||
val book = item.book
|
||||
item_book_title.text = book.getTitle()
|
||||
item_book_date.text = book.getDate()
|
||||
@ -59,24 +70,29 @@ sealed class BookOnDiskViewHolder<T : BooksOnDiskListItem>(containerView: View)
|
||||
item_book_label_video.visibility = View.GONE
|
||||
}
|
||||
|
||||
containerView.setOnClickListener {
|
||||
clickAction.invoke(item)
|
||||
}
|
||||
containerView.setOnLongClickListener {
|
||||
longClickAction?.invoke(item)
|
||||
return@setOnLongClickListener true
|
||||
when (selectionMode) {
|
||||
MULTI -> {
|
||||
itemBookCheckbox.visibility = View.VISIBLE
|
||||
containerView.setOnClickListener { multiSelectAction?.invoke(item) }
|
||||
containerView.setOnLongClickListener(null)
|
||||
}
|
||||
NORMAL -> {
|
||||
itemBookCheckbox.visibility = View.GONE
|
||||
containerView.setOnClickListener { clickAction.invoke(item) }
|
||||
containerView.setOnLongClickListener {
|
||||
longClickAction?.invoke(item)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageItemViewHolder(containerView: View) :
|
||||
BookOnDiskViewHolder<LanguageItem>(containerView) {
|
||||
|
||||
override fun bind(item: LanguageItem) {
|
||||
header_language.text = item.text
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LanguageItemViewHolder(containerView: View) :
|
||||
BookOnDiskViewHolder<LanguageItem>(containerView) {
|
||||
|
||||
override fun bind(item: LanguageItem) {
|
||||
header_language.text = item.text
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||
|
||||
import android.app.Activity
|
||||
import org.kiwix.kiwixmobile.R.string
|
||||
import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao
|
||||
import org.kiwix.kiwixmobile.extensions.toast
|
||||
import org.kiwix.kiwixmobile.utils.DialogShower
|
||||
import org.kiwix.kiwixmobile.utils.KiwixDialog.DeleteZim
|
||||
import org.kiwix.kiwixmobile.utils.files.FileUtils
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeleteFiles(val booksOnDiskListItem: List<BookOnDisk>) :
|
||||
SideEffect<Unit> {
|
||||
|
||||
@Inject lateinit var dialogShower: DialogShower
|
||||
@Inject lateinit var newBookDao: NewBookDao
|
||||
|
||||
override fun invokeWith(activity: Activity) {
|
||||
activityComponent(activity).inject(this)
|
||||
booksOnDiskListItem.forEach {
|
||||
dialogShower.show(DeleteZim, {
|
||||
if (deleteSpecificZimFile(it)) {
|
||||
activity.toast(string.delete_specific_zim_toast)
|
||||
} else {
|
||||
activity.toast(string.delete_zim_failed)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteSpecificZimFile(book: BookOnDisk): Boolean {
|
||||
val file = book.file
|
||||
FileUtils.deleteZimFile(file.path)
|
||||
if (file.exists()) {
|
||||
return false
|
||||
}
|
||||
newBookDao.delete(book.databaseId!!)
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||
|
||||
import android.app.Activity
|
||||
|
||||
object None : SideEffect<Unit> {
|
||||
override fun invokeWith(activity: Activity) {
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (C) 2018 Kiwix <android.kiwix.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||
|
||||
import android.app.Activity
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.data.ZimContentProvider
|
||||
import org.kiwix.kiwixmobile.extensions.toast
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageActivity
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
|
||||
class OpenFile(val bookOnDisk: BookOnDisk): SideEffect<Unit> {
|
||||
|
||||
override fun invokeWith(activity: Activity) {
|
||||
val file = bookOnDisk.file
|
||||
ZimContentProvider.canIterate = false
|
||||
if (!file.canRead()) {
|
||||
activity.toast(R.string.error_filenotfound)
|
||||
} else {
|
||||
(activity as ZimManageActivity).finishResult(file.path)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.content.FileProvider
|
||||
import org.kiwix.kiwixmobile.BuildConfig
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
|
||||
class ShareFiles(val selectedBooks: List<BookOnDisk>) : SideEffect<Unit> {
|
||||
override fun invokeWith(activity: Activity) {
|
||||
val selectedFileShareIntent = Intent()
|
||||
selectedFileShareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
||||
selectedFileShareIntent.type = "application/octet-stream"
|
||||
val selectedFileContentURIs = selectedBooks.mapNotNull {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
FileProvider.getUriForFile(
|
||||
activity,
|
||||
BuildConfig.APPLICATION_ID + ".fileprovider",
|
||||
it.file
|
||||
)
|
||||
} else {
|
||||
Uri.fromFile(it.file)
|
||||
}
|
||||
}
|
||||
selectedFileShareIntent.putParcelableArrayListExtra(
|
||||
Intent.EXTRA_STREAM,
|
||||
ArrayList(selectedFileContentURIs)
|
||||
)
|
||||
selectedFileShareIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
val shareChooserIntent = Intent.createChooser(
|
||||
selectedFileShareIntent,
|
||||
activity.getString(R.string.selected_file_cab_app_chooser_title)
|
||||
)
|
||||
if (shareChooserIntent.resolveActivity(activity.getPackageManager()) != null) {
|
||||
activity.startActivity(shareChooserIntent) // Open the app chooser dialog
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (C) 2018 Kiwix <android.kiwix.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||
|
||||
import android.app.Activity
|
||||
import org.kiwix.kiwixmobile.KiwixApplication
|
||||
|
||||
interface SideEffect<T:Any?> {
|
||||
fun invokeWith(activity: Activity):T
|
||||
fun activityComponent(activity: Activity) =
|
||||
KiwixApplication.getApplicationComponent().activityComponent().activity(activity).build()
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.ActionMode
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.extensions.startActionMode
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestDeleteMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions.RequestShareMultiSelection
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
|
||||
data class StartMultiSelection(
|
||||
val bookOnDisk: BooksOnDiskListItem.BookOnDisk,
|
||||
val fileSelectActions: PublishProcessor<FileSelectActions>
|
||||
) : SideEffect<ActionMode?> {
|
||||
override fun invokeWith(activity: Activity) =
|
||||
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) }
|
||||
)
|
||||
|
||||
}
|
@ -140,7 +140,7 @@ class LibraryFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
private fun onLibraryItemsChange(it: List<LibraryListItem>?) {
|
||||
libraryAdapter.itemList = it!!
|
||||
libraryAdapter.items = it!!
|
||||
if (it.isEmpty()) {
|
||||
libraryErrorText.setText(
|
||||
if (isNotConnected) R.string.no_network_connection
|
||||
|
@ -30,7 +30,7 @@ abstract class BaseDelegateAdapter<ITEM>(
|
||||
setHasStableIds(true)
|
||||
}
|
||||
|
||||
var itemList: List<ITEM> = mutableListOf()
|
||||
var items: List<ITEM> = mutableListOf()
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
@ -41,19 +41,19 @@ abstract class BaseDelegateAdapter<ITEM>(
|
||||
viewType: Int
|
||||
) = delegateManager.createViewHolder(parent, viewType)
|
||||
|
||||
override fun getItemCount() = itemList.size
|
||||
override fun getItemCount() = items.size
|
||||
override fun onBindViewHolder(
|
||||
holder: ViewHolder,
|
||||
position: Int
|
||||
) {
|
||||
delegateManager.onBindViewHolder(itemList[position], holder)
|
||||
delegateManager.onBindViewHolder(items[position], holder)
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int) =
|
||||
delegateManager.getViewTypeFor(itemList[position])
|
||||
delegateManager.getViewTypeFor(items[position])
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return getIdFor(itemList[position])
|
||||
return getIdFor(items[position])
|
||||
}
|
||||
|
||||
abstract fun getIdFor(item:ITEM):Long
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingRight="0dp"
|
||||
@ -12,13 +12,25 @@
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/itemBookCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_book_icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:contentDescription="@string/favicon"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/itemBookCheckbox"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@mipmap/kiwix_icon_round"
|
||||
/>
|
||||
|
@ -235,7 +235,7 @@ class ZimManageViewModelTest {
|
||||
val expectedList = listOf(bookOnDisk())
|
||||
booksOnDiskListItems.onNext(expectedList)
|
||||
testScheduler.triggerActions()
|
||||
viewModel.bookItems.test()
|
||||
viewModel.fileSelectListStates.test()
|
||||
.assertValue(expectedList)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user