-
-
Notifications
You must be signed in to change notification settings - Fork 468
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
884 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
app/src/main/java/eu/darken/sdmse/common/picker/PickerAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import android.view.ViewGroup | ||
import androidx.annotation.LayoutRes | ||
import androidx.viewbinding.ViewBinding | ||
import eu.darken.sdmse.common.lists.BindableVH | ||
import eu.darken.sdmse.common.lists.differ.AsyncDiffer | ||
import eu.darken.sdmse.common.lists.differ.DifferItem | ||
import eu.darken.sdmse.common.lists.differ.HasAsyncDiffer | ||
import eu.darken.sdmse.common.lists.differ.setupDiffer | ||
import eu.darken.sdmse.common.lists.modular.ModularAdapter | ||
import eu.darken.sdmse.common.lists.modular.mods.DataBinderMod | ||
import eu.darken.sdmse.common.lists.modular.mods.TypedVHCreatorMod | ||
import javax.inject.Inject | ||
|
||
|
||
class PickerAdapter @Inject constructor() : | ||
ModularAdapter<PickerAdapter.BaseVH<PickerAdapter.Item, ViewBinding>>(), | ||
HasAsyncDiffer<PickerAdapter.Item> { | ||
|
||
override val asyncDiffer: AsyncDiffer<*, Item> = setupDiffer() | ||
|
||
override fun getItemCount(): Int = data.size | ||
|
||
init { | ||
addMod(DataBinderMod(data)) | ||
addMod(TypedVHCreatorMod({ data[it] is PickerItemVH.Item }) { PickerItemVH(it) }) | ||
} | ||
|
||
abstract class BaseVH<D : Item, B : ViewBinding>( | ||
@LayoutRes layoutId: Int, | ||
parent: ViewGroup | ||
) : VH(layoutId, parent), BindableVH<D, B> | ||
|
||
interface Item : DifferItem { | ||
|
||
override val payloadProvider: ((DifferItem, DifferItem) -> DifferItem?) | ||
get() = { old, new -> | ||
if (new::class.isInstance(old)) new else null | ||
} | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
app/src/main/java/eu/darken/sdmse/common/picker/PickerEvents.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
sealed class PickerEvents { | ||
data object ExitConfirmation : PickerEvents() | ||
} |
126 changes: 126 additions & 0 deletions
126
app/src/main/java/eu/darken/sdmse/common/picker/PickerFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import android.os.Bundle | ||
import android.view.View | ||
import android.widget.LinearLayout | ||
import androidx.activity.OnBackPressedCallback | ||
import androidx.core.view.isInvisible | ||
import androidx.core.view.iterator | ||
import androidx.fragment.app.viewModels | ||
import androidx.recyclerview.widget.GridLayoutManager | ||
import com.google.android.material.bottomsheet.BottomSheetBehavior | ||
import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||
import dagger.hilt.android.AndroidEntryPoint | ||
import eu.darken.sdmse.R | ||
import eu.darken.sdmse.common.debug.logging.log | ||
import eu.darken.sdmse.common.debug.logging.logTag | ||
import eu.darken.sdmse.common.dpToPx | ||
import eu.darken.sdmse.common.getQuantityString2 | ||
import eu.darken.sdmse.common.lists.differ.update | ||
import eu.darken.sdmse.common.lists.setupDefaults | ||
import eu.darken.sdmse.common.navigation.getSpanCount | ||
import eu.darken.sdmse.common.uix.Fragment3 | ||
import eu.darken.sdmse.common.viewbinding.viewBinding | ||
import eu.darken.sdmse.databinding.CommonPickerFragmentBinding | ||
import kotlin.math.roundToInt | ||
|
||
@AndroidEntryPoint | ||
class PickerFragment : Fragment3(R.layout.common_picker_fragment) { | ||
|
||
override val vm: PickerViewModel by viewModels() | ||
override val ui: CommonPickerFragmentBinding by viewBinding() | ||
|
||
private lateinit var selectedContainer: BottomSheetBehavior<LinearLayout> | ||
|
||
private val onBackPressedcallback = object : OnBackPressedCallback(true) { | ||
override fun handleOnBackPressed() { | ||
vm.goBack() | ||
} | ||
} | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
requireActivity().onBackPressedDispatcher.addCallback(this, onBackPressedcallback) | ||
} | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
selectedContainer = BottomSheetBehavior.from(ui.selectedContainer).apply { | ||
isHideable = false | ||
state = BottomSheetBehavior.STATE_COLLAPSED | ||
peekHeight = requireContext().dpToPx(64f) | ||
ui.root.post { | ||
maxHeight = ((ui.root.height - ui.toolbar.height) * 0.5f).roundToInt() | ||
} | ||
} | ||
|
||
ui.toolbar.apply { | ||
setNavigationOnClickListener { vm.cancel(confirmed = false) } | ||
setOnMenuItemClickListener { | ||
when (it.itemId) { | ||
R.id.menu_action_save -> { | ||
vm.save() | ||
true | ||
} | ||
|
||
R.id.menu_action_home -> { | ||
vm.home() | ||
true | ||
} | ||
|
||
R.id.menu_action_select_all -> { | ||
vm.selectAll() | ||
true | ||
} | ||
|
||
else -> false | ||
} | ||
} | ||
} | ||
|
||
val pickerAdapter = PickerAdapter() | ||
ui.list.setupDefaults( | ||
pickerAdapter, | ||
horizontalDividers = true, | ||
layouter = GridLayoutManager(context, getSpanCount(), GridLayoutManager.VERTICAL, false), | ||
) | ||
val selectedAdapter = PickerSelectedAdapter() | ||
ui.selectedList.setupDefaults( | ||
selectedAdapter, | ||
horizontalDividers = true, | ||
) | ||
vm.state.observe2(ui) { state -> | ||
log(TAG) { "updating with new state: $state" } | ||
toolbar.subtitle = state.current?.lookup?.path ?: "" | ||
toolbar.menu.iterator().forEach { it.isVisible = state.progress == null } | ||
|
||
loadingOverlay.setProgress(state.progress) | ||
if (state.progress == null) pickerAdapter.update(state.items) | ||
list.isInvisible = state.progress != null | ||
|
||
selectedList.isInvisible = state.progress != null | ||
selectedSecondary.text = requireContext().getQuantityString2( | ||
R.plurals.picker_selected_paths_subtitle, | ||
state.selected.size, | ||
) | ||
if (state.progress == null) selectedAdapter.update(state.selected) | ||
} | ||
|
||
vm.events.observe2 { event -> | ||
when (event) { | ||
PickerEvents.ExitConfirmation -> MaterialAlertDialogBuilder(requireContext()).apply { | ||
setMessage(R.string.picker_unsaved_confirmation_message) | ||
setPositiveButton(eu.darken.sdmse.common.R.string.general_discard_action) { _, _ -> | ||
vm.cancel(confirmed = true) | ||
} | ||
setNegativeButton(eu.darken.sdmse.common.R.string.general_cancel_action) { _, _ -> } | ||
}.show() | ||
} | ||
} | ||
|
||
super.onViewCreated(view, savedInstanceState) | ||
} | ||
|
||
companion object { | ||
private val TAG = logTag("Common", "Picker", "Fragment") | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
app/src/main/java/eu/darken/sdmse/common/picker/PickerItem.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import eu.darken.sdmse.common.areas.DataArea | ||
import eu.darken.sdmse.common.files.APathLookup | ||
|
||
data class PickerItem( | ||
val lookup: APathLookup<*>, | ||
val parent: PickerItem?, | ||
val dataArea: DataArea, | ||
val selected: Boolean, | ||
val selectable: Boolean, | ||
) |
71 changes: 71 additions & 0 deletions
71
app/src/main/java/eu/darken/sdmse/common/picker/PickerItemVH.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import android.view.ViewGroup | ||
import androidx.core.view.isVisible | ||
import coil.dispose | ||
import eu.darken.sdmse.R | ||
import eu.darken.sdmse.common.areas.label | ||
import eu.darken.sdmse.common.coil.loadFilePreview | ||
import eu.darken.sdmse.common.files.APath | ||
import eu.darken.sdmse.common.files.FileType | ||
import eu.darken.sdmse.common.lists.binding | ||
import eu.darken.sdmse.databinding.CommonPickerItemBinding | ||
|
||
|
||
class PickerItemVH(parent: ViewGroup) : | ||
PickerAdapter.BaseVH<PickerItemVH.Item, CommonPickerItemBinding>( | ||
R.layout.common_picker_item, | ||
parent | ||
) { | ||
|
||
override val viewBinding = lazy { CommonPickerItemBinding.bind(itemView) } | ||
|
||
override val onBindData: CommonPickerItemBinding.( | ||
item: Item, | ||
payloads: List<Any> | ||
) -> Unit = binding { wrapper -> | ||
val item = wrapper.item | ||
|
||
contentIcon.apply { | ||
if (item.parent == null) { | ||
setImageResource(R.drawable.ic_folder_home_24) | ||
} else { | ||
dispose() | ||
loadFilePreview(item.lookup) | ||
} | ||
} | ||
|
||
primary.text = when { | ||
item.parent == null -> item.lookup.path | ||
else -> item.lookup.name | ||
} | ||
secondary.text = item.dataArea.type.label.get(context) | ||
tertiary.text = when (item.lookup.fileType) { | ||
FileType.DIRECTORY -> getString(eu.darken.sdmse.common.R.string.file_type_directory) | ||
FileType.FILE -> getString(eu.darken.sdmse.common.R.string.file_type_file) | ||
FileType.SYMBOLIC_LINK -> getString(eu.darken.sdmse.common.R.string.file_type_symbolic_link) | ||
FileType.UNKNOWN -> getString(eu.darken.sdmse.common.R.string.file_type_unknown) | ||
} | ||
|
||
indicator.apply { | ||
isChecked = item.selected | ||
isVisible = item.selectable | ||
setOnClickListener { wrapper.onSelect?.invoke() } | ||
} | ||
|
||
root.setOnClickListener { wrapper.onItemClicked() } | ||
} | ||
|
||
data class Item( | ||
val item: PickerItem, | ||
val onItemClicked: () -> Unit, | ||
val onSelect: (() -> Unit)?, | ||
) : PickerAdapter.Item { | ||
|
||
val path: APath | ||
get() = item.lookup.lookedUp | ||
|
||
override val stableId: Long = path.hashCode().toLong() | ||
} | ||
|
||
} |
17 changes: 17 additions & 0 deletions
17
app/src/main/java/eu/darken/sdmse/common/picker/PickerRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import android.os.Parcelable | ||
import eu.darken.sdmse.common.areas.DataArea | ||
import eu.darken.sdmse.common.files.APath | ||
import kotlinx.parcelize.Parcelize | ||
|
||
@Parcelize | ||
data class PickerRequest( | ||
val mode: PickMode, | ||
val allowedAreas: Set<DataArea.Type> = emptySet(), | ||
val selectedPaths: List<APath> = emptyList(), | ||
) : Parcelable { | ||
enum class PickMode { | ||
MIXED, FILE, FILES, DIR, DIRS | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
app/src/main/java/eu/darken/sdmse/common/picker/PickerSelectedAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import android.view.ViewGroup | ||
import androidx.annotation.LayoutRes | ||
import androidx.viewbinding.ViewBinding | ||
import eu.darken.sdmse.common.lists.BindableVH | ||
import eu.darken.sdmse.common.lists.differ.AsyncDiffer | ||
import eu.darken.sdmse.common.lists.differ.DifferItem | ||
import eu.darken.sdmse.common.lists.differ.HasAsyncDiffer | ||
import eu.darken.sdmse.common.lists.differ.setupDiffer | ||
import eu.darken.sdmse.common.lists.modular.ModularAdapter | ||
import eu.darken.sdmse.common.lists.modular.mods.DataBinderMod | ||
import eu.darken.sdmse.common.lists.modular.mods.TypedVHCreatorMod | ||
import javax.inject.Inject | ||
|
||
|
||
class PickerSelectedAdapter @Inject constructor() : | ||
ModularAdapter<PickerSelectedAdapter.BaseVH<PickerSelectedAdapter.Item, ViewBinding>>(), | ||
HasAsyncDiffer<PickerSelectedAdapter.Item> { | ||
|
||
override val asyncDiffer: AsyncDiffer<*, Item> = setupDiffer() | ||
|
||
override fun getItemCount(): Int = data.size | ||
|
||
init { | ||
addMod(DataBinderMod(data)) | ||
addMod(TypedVHCreatorMod({ data[it] is PickerSelectedVH.Item }) { PickerSelectedVH(it) }) | ||
} | ||
|
||
abstract class BaseVH<D : Item, B : ViewBinding>(@LayoutRes layoutId: Int, parent: ViewGroup) : | ||
VH(layoutId, parent), BindableVH<D, B> | ||
|
||
interface Item : DifferItem { | ||
override val payloadProvider: ((DifferItem, DifferItem) -> DifferItem?) | ||
get() = { old, new -> if (new::class.isInstance(old)) new else null } | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
app/src/main/java/eu/darken/sdmse/common/picker/PickerSelectedVH.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package eu.darken.sdmse.common.picker | ||
|
||
import android.view.ViewGroup | ||
import eu.darken.sdmse.R | ||
import eu.darken.sdmse.common.files.APathLookup | ||
import eu.darken.sdmse.common.files.iconRes | ||
import eu.darken.sdmse.common.lists.binding | ||
import eu.darken.sdmse.databinding.CommonPickerSelectedItemBinding | ||
|
||
|
||
class PickerSelectedVH(parent: ViewGroup) : | ||
PickerSelectedAdapter.BaseVH<PickerSelectedVH.Item, CommonPickerSelectedItemBinding>( | ||
R.layout.common_picker_selected_item, | ||
parent | ||
) { | ||
|
||
override val viewBinding = lazy { CommonPickerSelectedItemBinding.bind(itemView) } | ||
|
||
override val onBindData: CommonPickerSelectedItemBinding.( | ||
item: Item, | ||
payloads: List<Any> | ||
) -> Unit = binding { item -> | ||
icon.setImageResource(item.lookup.fileType.iconRes) | ||
primary.text = item.lookup.userReadablePath.get(context) | ||
removeAction.setOnClickListener { item.onRemove() } | ||
} | ||
|
||
data class Item( | ||
val lookup: APathLookup<*>, | ||
val onRemove: () -> Unit, | ||
) : PickerSelectedAdapter.Item { | ||
override val stableId: Long = lookup.path.hashCode().toLong() | ||
} | ||
|
||
} |
Oops, something went wrong.