Skip to content

Commit 27dbc34

Browse files
author
Majid Arabi
committed
Merge remote-tracking branch 'origin/dev'
# Conflicts: # file-picker/build.gradle
2 parents 0ba9f2c + d382205 commit 27dbc34

File tree

16 files changed

+229
-78
lines changed

16 files changed

+229
-78
lines changed

app/src/main/java/ir/one_developer/filepickerlibrary/FileAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import androidx.core.net.toUri
66
import androidx.recyclerview.widget.DiffUtil
77
import androidx.recyclerview.widget.ListAdapter
88
import androidx.recyclerview.widget.RecyclerView
9-
import com.github.file_picker.model.Media
9+
import com.github.file_picker.data.model.Media
1010
import ir.one_developer.filepickerlibrary.databinding.FileLayoutBinding
1111
import java.io.File
1212

app/src/main/java/ir/one_developer/filepickerlibrary/MainActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import com.github.file_picker.adapter.FilePickerAdapter
88
import com.github.file_picker.extension.showFilePicker
99
import com.github.file_picker.listener.OnItemClickListener
1010
import com.github.file_picker.listener.OnSubmitClickListener
11-
import com.github.file_picker.model.Media
11+
import com.github.file_picker.data.model.Media
1212
import ir.one_developer.filepickerlibrary.databinding.ActivityMainBinding
1313

1414
class MainActivity : AppCompatActivity() {
@@ -65,6 +65,7 @@ class MainActivity : AppCompatActivity() {
6565
limitItemSelection = limit,
6666
gridSpanCount = spanCount,
6767
selectedFiles = selectedFiles,
68+
overlayAlpha = 0.75f,
6869
accentColor = ContextCompat.getColor(this@MainActivity, accentColor),
6970
titleTextColor = ContextCompat.getColor(this@MainActivity, accentColor),
7071
onSubmitClickListener = object : OnSubmitClickListener {

file-picker/build.gradle

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,32 @@ android {
3535
}
3636

3737
dependencies {
38-
implementation 'androidx.core:core-ktx:1.7.0'
38+
implementation 'androidx.core:core-ktx:1.8.0'
3939
implementation 'androidx.appcompat:appcompat:1.4.1'
4040
implementation 'androidx.recyclerview:recyclerview:1.2.1'
41-
implementation 'com.google.android.material:material:1.5.0'
41+
implementation 'com.google.android.material:material:1.6.1'
4242

43-
// Coroutines
44-
def coroutine_version = "1.6.0"
43+
def activity_version = "1.5.1"
44+
implementation "androidx.activity:activity-ktx:$activity_version"
45+
46+
def fragment_version = "1.5.2"
47+
implementation "androidx.fragment:fragment-ktx:$fragment_version"
48+
49+
def coroutine_version = "1.6.1"
4550
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
4651
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
4752

48-
// Glide
4953
def glide_version = "4.13.0"
5054
implementation "com.github.bumptech.glide:glide:$glide_version"
5155
annotationProcessor "com.github.bumptech.glide:compiler:$glide_version"
56+
57+
def paging_version = "3.1.1"
58+
implementation "androidx.paging:paging-runtime:$paging_version"
59+
60+
def lifecycle_version = "2.5.1"
61+
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
62+
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
63+
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
5264
}
5365

5466
afterEvaluate {
@@ -58,7 +70,7 @@ afterEvaluate {
5870
from components.release
5971
groupId = 'com.github.majidarabi'
6072
artifactId = 'file-picker'
61-
version = '0.1.0'
73+
version = '0.0.9'
6274
}
6375
}
6476
}

file-picker/src/main/java/com/github/file_picker/Const.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ enum class FileType : Parcelable {
1414
VIDEO,
1515
IMAGE,
1616
AUDIO,
17-
}
17+
}
18+
19+
const val PAGE_SIZE = 10

file-picker/src/main/java/com/github/file_picker/FilePicker.kt

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ import android.view.View
1010
import android.view.ViewGroup
1111
import androidx.activity.result.contract.ActivityResultContracts
1212
import androidx.annotation.ColorInt
13+
import androidx.annotation.FloatRange
1314
import androidx.appcompat.app.AppCompatActivity
1415
import androidx.core.view.isVisible
1516
import androidx.fragment.app.FragmentManager
17+
import androidx.paging.LoadState
1618
import androidx.recyclerview.widget.GridLayoutManager
1719
import androidx.recyclerview.widget.RecyclerView
1820
import com.github.file_picker.adapter.ItemAdapter
19-
import com.github.file_picker.extension.getStorageFiles
21+
import com.github.file_picker.data.model.Media
22+
import com.github.file_picker.data.repository.FilesRepository
2023
import com.github.file_picker.extension.hasPermission
2124
import com.github.file_picker.listener.OnItemClickListener
2225
import com.github.file_picker.listener.OnSubmitClickListener
23-
import com.github.file_picker.model.Media
2426
import com.google.android.material.bottomsheet.BottomSheetBehavior
2527
import com.google.android.material.bottomsheet.BottomSheetDialog
2628
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
@@ -49,6 +51,7 @@ class FilePicker private constructor(
4951
private var _binding: FilePickerBinding? = null
5052

5153
private var itemsAdapter: ItemAdapter? = null
54+
private lateinit var repository: FilesRepository
5255

5356
private var title: String
5457
private var titleTextColor by Delegates.notNull<Int>()
@@ -61,6 +64,7 @@ class FilePicker private constructor(
6164
private var accentColor by Delegates.notNull<Int>()
6265
private var gridSpanCount by Delegates.notNull<Int>()
6366
private var cancellable by Delegates.notNull<Boolean>()
67+
private var overlayAlpha by Delegates.notNull<Float>()
6468

6569
private var onItemClickListener: OnItemClickListener?
6670
private var onSubmitClickListener: OnSubmitClickListener?
@@ -77,6 +81,7 @@ class FilePicker private constructor(
7781
this.gridSpanCount = builder.gridSpanCount
7882
this.limitCount = builder.limitCount
7983
this.accentColor = builder.accentColor
84+
this.overlayAlpha = builder.overlayAlpha
8085
this.onItemClickListener = builder.onItemClickListener
8186
this.onSubmitClickListener = builder.onSubmitClickListener
8287
}
@@ -116,6 +121,8 @@ class FilePicker private constructor(
116121
private set
117122
var onSubmitClickListener: OnSubmitClickListener? = null
118123
private set
124+
var overlayAlpha: Float = DEFAULT_OVERLAY_ALPHA
125+
private set
119126

120127
/**
121128
* Set title
@@ -228,14 +235,21 @@ class FilePicker private constructor(
228235
) = apply { this.onItemClickListener = onItemClickListener }
229236

230237
/**
231-
* Build file picker instance
238+
* Set overlay alpha
232239
*
240+
* @param alpha
241+
*/
242+
fun setOverlayAlpha(
243+
alpha: Float
244+
) = apply { this.overlayAlpha = alpha }
245+
246+
/**
247+
* Build file picker instance
233248
*/
234249
fun build() = FilePicker(this)
235250

236251
/**
237252
* Build file picker and show it
238-
*
239253
*/
240254
fun buildAndShow() = build().show(
241255
appCompatActivity.supportFragmentManager,
@@ -257,6 +271,7 @@ class FilePicker private constructor(
257271
}
258272

259273
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
274+
repository = FilesRepository(requireActivity().application)
260275
setCancellableDialog(cancellable)
261276
setupViews()
262277
}
@@ -365,6 +380,7 @@ class FilePicker private constructor(
365380
private fun setupRecyclerView(recyclerView: RecyclerView) {
366381
itemsAdapter = ItemAdapter(
367382
accentColor = accentColor,
383+
overlayAlpha = overlayAlpha,
368384
limitSelectionCount = limitCount,
369385
listener = { itemPosition ->
370386
setupOnItemClickListener(itemPosition)
@@ -390,7 +406,7 @@ class FilePicker private constructor(
390406
private fun setupOnItemClickListener(position: Int) {
391407
if (onItemClickListener == null) return
392408
if (itemsAdapter == null) return
393-
val media = itemsAdapter?.currentList?.get(position) ?: return
409+
val media = itemsAdapter?.snapshot()?.items?.get(position) ?: return
394410
onItemClickListener?.onClick(media, position, itemsAdapter!!)
395411
}
396412

@@ -411,34 +427,29 @@ class FilePicker private constructor(
411427

412428
/**
413429
* Load files
414-
*
415430
*/
416431
private fun loadFiles() = CoroutineScope(Dispatchers.IO).launch {
417-
val files = getStorageFiles(fileType = fileType)
418-
.map { Media(file = it, type = fileType) }
419-
420-
if (selectedFiles.isNotEmpty()) {
421-
selectedFiles.forEach { media ->
422-
val selectedMedia = files.find { it.id == media.id }
423-
if (selectedMedia != null) {
424-
selectedMedia.isSelected = media.isSelected
425-
selectedMedia.order = media.order
432+
itemsAdapter?.addLoadStateListener { state ->
433+
binding.progress.isVisible = state.source.refresh is LoadState.Loading
434+
if (state.source.refresh is LoadState.NotLoading) {
435+
selectedFiles.forEach { media ->
436+
itemsAdapter?.snapshot()?.items?.find { it.id == media.id }?.let {
437+
it.isSelected = media.isSelected
438+
it.order = media.order
439+
}
426440
}
441+
updateSelectedCount()
442+
setFixedSubmitButton()
443+
changeSubmitButtonState()
427444
}
428445
}
429-
430-
requireActivity().runOnUiThread {
431-
itemsAdapter?.submitList(files)
432-
updateSelectedCount()
433-
setFixedSubmitButton()
434-
changeSubmitButtonState()
435-
binding.progress.isVisible = false
446+
repository.getFiles(fileType = fileType).collect { pagingData ->
447+
itemsAdapter?.submitData(pagingData)
436448
}
437449
}
438450

439451
/**
440452
* Submit list
441-
*
442453
*/
443454
private fun submitList() = getSelectedItems()?.let {
444455
onSubmitClickListener?.onClick(it)
@@ -450,7 +461,7 @@ class FilePicker private constructor(
450461
* @return
451462
*/
452463
private fun getSelectedItems(): List<Media>? =
453-
itemsAdapter?.currentList?.filter { it.isSelected }?.sortedBy { it.order }
464+
itemsAdapter?.snapshot()?.items?.filter { it.isSelected }?.sortedBy { it.order }
454465

455466
/**
456467
* Has selected item
@@ -471,6 +482,9 @@ class FilePicker private constructor(
471482
const val DEFAULT_TITLE = "Choose File"
472483
const val DEFAULT_TITLE_TEXT_COLOR = DEFAULT_ACCENT_COLOR
473484

485+
@FloatRange(from = 0.0, to = 1.0)
486+
const val DEFAULT_OVERLAY_ALPHA = 0.5F
487+
474488
const val DEFAULT_SUBMIT_TEXT = "Submit"
475489
const val DEFAULT_SUBMIT_TEXT_COLOR = Color.WHITE
476490

file-picker/src/main/java/com/github/file_picker/adapter/ItemAdapter.kt

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,26 @@ package com.github.file_picker.adapter
22

33
import android.view.LayoutInflater
44
import android.view.ViewGroup
5+
import androidx.paging.PagingDataAdapter
56
import androidx.recyclerview.widget.DiffUtil
67
import androidx.recyclerview.widget.ListAdapter
78
import com.github.file_picker.FilePicker
89
import com.github.file_picker.extension.isValidPosition
9-
import com.github.file_picker.model.Media
10+
import com.github.file_picker.data.model.Media
1011
import ir.one_developer.file_picker.databinding.ItemLayoutBinding
12+
import java.util.Locale.filter
1113

1214
internal class ItemAdapter(
1315
private var accentColor: Int = FilePicker.DEFAULT_ACCENT_COLOR,
16+
private var overlayAlpha: Float = FilePicker.DEFAULT_OVERLAY_ALPHA,
1417
private var limitSelectionCount: Int = FilePicker.DEFAULT_LIMIT_COUNT,
1518
private var listener: ((Int) -> Unit)? = null
16-
) : ListAdapter<Media, ItemVH>(COMPARATOR), FilePickerAdapter {
19+
) : PagingDataAdapter<Media, ItemVH>(COMPARATOR), FilePickerAdapter {
1720

1821
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ItemVH(
1922
listener = listener,
2023
accentColor = accentColor,
24+
overlayAlpha =overlayAlpha,
2125
limitSelectionCount = limitSelectionCount,
2226
binding = ItemLayoutBinding.inflate(
2327
LayoutInflater.from(parent.context),
@@ -27,7 +31,7 @@ internal class ItemAdapter(
2731
)
2832

2933
override fun onBindViewHolder(holder: ItemVH, position: Int) {
30-
holder.bind(getItem(position))
34+
getItem(position)?.let { holder.bind(it) }
3135
}
3236

3337
/**
@@ -37,8 +41,8 @@ internal class ItemAdapter(
3741
*/
3842
override fun setSelected(position: Int) {
3943
if (limitSelectionCount > 1) {
40-
val item = getItem(position)
41-
val selectedItems = currentList.filter { it.isSelected && it.id != item.id }
44+
val item = getItem(position) ?: return
45+
val selectedItems = snapshot().items.filter { it.isSelected && it.id != item.id }
4246
val selectedItemCount = selectedItems.size
4347

4448
if (item.isSelected) {
@@ -47,7 +51,7 @@ internal class ItemAdapter(
4751
selectedItems.forEach { media ->
4852
if (media.order > item.order) {
4953
media.order--
50-
notifyItemChanged(currentList.indexOf(media))
54+
notifyItemChanged(snapshot().items.indexOf(media))
5155
}
5256
}
5357
return
@@ -61,22 +65,16 @@ internal class ItemAdapter(
6165
return
6266
}
6367

64-
if (!currentList.isValidPosition(lastSelectedPosition)) {
68+
if (!snapshot().items.isValidPosition(lastSelectedPosition)) {
6569
lastSelectedPosition = position
6670
}
67-
getItem(lastSelectedPosition).isSelected = false
71+
getItem(lastSelectedPosition)?.isSelected = false
6872
notifyItemChanged(lastSelectedPosition)
6973
lastSelectedPosition = position
70-
getItem(lastSelectedPosition).isSelected = true
74+
getItem(lastSelectedPosition)?.isSelected = true
7175
notifyItemChanged(lastSelectedPosition)
7276
}
7377

74-
override fun setHasStableIds(hasStableIds: Boolean) {
75-
super.setHasStableIds(true)
76-
}
77-
78-
override fun getItemId(position: Int): Long = getItem(position).id.toLong()
79-
8078
companion object {
8179
private var lastSelectedPosition = -1
8280

file-picker/src/main/java/com/github/file_picker/adapter/ItemVH.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,25 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
1111
import com.bumptech.glide.request.RequestListener
1212
import com.bumptech.glide.request.target.Target
1313
import com.github.file_picker.FileType
14+
import com.github.file_picker.data.model.Media
1415
import com.github.file_picker.extension.getMusicCoverArt
1516
import com.github.file_picker.extension.lastPathTitle
1617
import com.github.file_picker.extension.size
17-
import com.github.file_picker.model.Media
1818
import ir.one_developer.file_picker.R
1919
import ir.one_developer.file_picker.databinding.ItemLayoutBinding
2020

2121
internal class ItemVH(
2222
private val listener: ((Int) -> Unit)?,
2323
private val binding: ItemLayoutBinding,
2424
private val accentColor: Int,
25+
private val overlayAlpha: Float,
2526
private val limitSelectionCount: Int
2627
) : RecyclerView.ViewHolder(binding.root) {
2728

2829
init {
2930
binding.apply {
3031
frameChecked.setBackgroundColor(accentColor)
32+
frameChecked.alpha = overlayAlpha
3133
card.setOnClickListener {
3234
listener?.invoke(bindingAdapterPosition)
3335
}
@@ -63,7 +65,7 @@ internal class ItemVH(
6365

6466
Glide.with(ivImage)
6567
.load(previewImage)
66-
.diskCacheStrategy(DiskCacheStrategy.NONE)
68+
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
6769
.transition(DrawableTransitionOptions.withCrossFade())
6870
.listener(object : RequestListener<Drawable> {
6971
override fun onLoadFailed(
@@ -82,20 +84,18 @@ internal class ItemVH(
8284
target: Target<Drawable>?,
8385
dataSource: DataSource?,
8486
isFirstResource: Boolean
85-
): Boolean {
86-
return false
87-
}
88-
87+
): Boolean = false
8988
})
9089
.into(ivImage)
9190
}
9291

9392
private fun setErrorState(type: FileType) = binding.apply {
9493
cardErrorState.isVisible = true
9594
when (type) {
96-
FileType.AUDIO -> ivErrorIcon.setImageResource(R.drawable.ic_audiotrack)
97-
FileType.IMAGE -> ivErrorIcon.setImageResource(R.drawable.ic_image)
98-
FileType.VIDEO -> ivErrorIcon.setImageResource(R.drawable.ic_play)
95+
FileType.VIDEO -> Glide.with(ivErrorIcon).load(R.drawable.ic_play).into(ivErrorIcon)
96+
FileType.IMAGE -> Glide.with(ivErrorIcon).load(R.drawable.ic_image).into(ivErrorIcon)
97+
FileType.AUDIO -> Glide.with(ivErrorIcon).load(R.drawable.ic_audiotrack)
98+
.into(ivErrorIcon)
9999
}
100100
}
101101

0 commit comments

Comments
 (0)