handle media grouping at the MediaActivity
This commit is contained in:
parent
e759270019
commit
698f9b0c76
|
@ -283,8 +283,9 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
Thread {
|
||||
val filtered = mMedia.filter { it.name.contains(text, true) } as ArrayList
|
||||
filtered.sortBy { !it.name.startsWith(text, true) }
|
||||
val groupedMedia = MediaFetcher(applicationContext).groupMedia(filtered, mPath)
|
||||
runOnUiThread {
|
||||
getMediaAdapter()?.updateMedia(filtered)
|
||||
getMediaAdapter()?.updateMedia(groupedMedia)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
@ -315,12 +316,12 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
return
|
||||
}
|
||||
|
||||
val media = mMedia.clone() as ArrayList<Medium>
|
||||
val groupedMedia = MediaFetcher(applicationContext).groupMedia(mMedia.clone() as ArrayList<Medium>, mPath)
|
||||
val currAdapter = media_grid.adapter
|
||||
if (currAdapter == null) {
|
||||
initZoomListener()
|
||||
val fastscroller = if (config.scrollHorizontally) media_horizontal_fastscroller else media_vertical_fastscroller
|
||||
MediaAdapter(this, media, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, mAllowPickingMultiple, media_grid, fastscroller, mPath) {
|
||||
MediaAdapter(this, groupedMedia, this, mIsGetImageIntent || mIsGetVideoIntent || mIsGetAnyIntent, mAllowPickingMultiple, media_grid, fastscroller) {
|
||||
itemClicked((it as ThumbnailMedium).path)
|
||||
}.apply {
|
||||
setupZoomListener(mZoomListener)
|
||||
|
@ -328,8 +329,9 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
}
|
||||
setupLayoutManager()
|
||||
} else {
|
||||
(currAdapter as MediaAdapter).updateMedia(media)
|
||||
(currAdapter as MediaAdapter).updateMedia(groupedMedia)
|
||||
}
|
||||
|
||||
setupScrollDirection()
|
||||
}
|
||||
|
||||
|
@ -359,8 +361,9 @@ class MediaActivity : SimpleActivity(), MediaAdapter.MediaOperationsListener {
|
|||
private fun getBubbleTextItem(index: Int, sorting: Int) = getMediaAdapter()?.getItemBubbleText(index, sorting) ?: ""
|
||||
|
||||
private fun checkLastMediaChanged() {
|
||||
if (isActivityDestroyed())
|
||||
if (isActivityDestroyed()) {
|
||||
return
|
||||
}
|
||||
|
||||
mLastMediaHandler.removeCallbacksAndMessages(null)
|
||||
mLastMediaHandler.postDelayed({
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.simplemobiletools.gallery.adapters
|
|||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.format.DateFormat
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -19,19 +18,16 @@ import com.simplemobiletools.commons.views.MyRecyclerView
|
|||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.dialogs.DeleteWithRememberDialog
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.helpers.*
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.helpers.VIEW_TYPE_LIST
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import com.simplemobiletools.gallery.models.ThumbnailMedium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailSection
|
||||
import kotlinx.android.synthetic.main.photo_video_item_grid.view.*
|
||||
import kotlinx.android.synthetic.main.thumbnail_section.view.*
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>, val listener: MediaOperationsListener?, val isAGetIntent: Boolean,
|
||||
val allowMultiplePicks: Boolean, recyclerView: MyRecyclerView, fastScroller: FastScroller? = null, val path: String,
|
||||
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<ThumbnailItem>, val listener: MediaOperationsListener?, val isAGetIntent: Boolean,
|
||||
val allowMultiplePicks: Boolean, recyclerView: MyRecyclerView, fastScroller: FastScroller? = null, itemClick: (Any) -> Unit) :
|
||||
MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
|
||||
private val INSTANT_LOAD_DURATION = 2000L
|
||||
private val IMAGE_LOAD_DELAY = 100L
|
||||
|
@ -41,13 +37,10 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
private val config = activity.config
|
||||
private val isListViewType = config.viewTypeFiles == VIEW_TYPE_LIST
|
||||
private var visibleItemPaths = ArrayList<String>()
|
||||
private var thumbnailItems = ArrayList<ThumbnailItem>()
|
||||
private var loadImageInstantly = false
|
||||
private var delayHandler = Handler(Looper.getMainLooper())
|
||||
private var currentMediaHash = media.hashCode()
|
||||
private var currentGrouping = GROUP_BY_NONE
|
||||
private val hasOTGConnected = activity.hasOTGConnected()
|
||||
private var mediumGroups = LinkedHashMap<String, ArrayList<Medium>>()
|
||||
|
||||
private var scrollHorizontally = config.scrollHorizontally
|
||||
private var animateGifs = config.animateGifs
|
||||
|
@ -56,7 +49,6 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
|
||||
init {
|
||||
setupDragListener(true)
|
||||
groupMedia()
|
||||
enableInstantLoad()
|
||||
}
|
||||
|
||||
|
@ -84,7 +76,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val tmbItem = thumbnailItems.getOrNull(position) ?: return
|
||||
val tmbItem = media.getOrNull(position) ?: return
|
||||
if (tmbItem is ThumbnailMedium) {
|
||||
visibleItemPaths.add(tmbItem.path)
|
||||
}
|
||||
|
@ -99,10 +91,10 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
bindViewHolder(holder, position, view)
|
||||
}
|
||||
|
||||
override fun getItemCount() = thumbnailItems.size
|
||||
override fun getItemCount() = media.size
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val tmbItem = thumbnailItems[position]
|
||||
val tmbItem = media[position]
|
||||
return if (tmbItem is ThumbnailSection) {
|
||||
ITEM_SECTION
|
||||
} else {
|
||||
|
@ -145,7 +137,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = thumbnailItems.filter { it is ThumbnailMedium }.size
|
||||
override fun getSelectableItemCount() = media.filter { it is ThumbnailMedium }.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = !isASectionTitle(position)
|
||||
|
||||
|
@ -161,7 +153,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
}
|
||||
|
||||
fun isASectionTitle(position: Int) = thumbnailItems.getOrNull(position) is ThumbnailSection
|
||||
fun isASectionTitle(position: Int) = media.getOrNull(position) is ThumbnailSection
|
||||
|
||||
private fun checkHideBtnVisibility(menu: Menu) {
|
||||
var hiddenCnt = 0
|
||||
|
@ -199,7 +191,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
|
||||
private fun showProperties() {
|
||||
if (selectedPositions.size <= 1) {
|
||||
PropertiesDialog(activity, (thumbnailItems[selectedPositions.first()] as ThumbnailMedium).path, config.shouldShowHidden)
|
||||
PropertiesDialog(activity, (media[selectedPositions.first()] as ThumbnailMedium).path, config.shouldShowHidden)
|
||||
} else {
|
||||
val paths = getSelectedPaths()
|
||||
PropertiesDialog(activity, paths, config.shouldShowHidden)
|
||||
|
@ -293,7 +285,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}
|
||||
}
|
||||
|
||||
private fun getCurrentPath() = (thumbnailItems[selectedPositions.first()] as ThumbnailMedium).path
|
||||
private fun getCurrentPath() = (media[selectedPositions.first()] as ThumbnailMedium).path
|
||||
|
||||
private fun deleteFiles() {
|
||||
if (selectedPositions.isEmpty()) {
|
||||
|
@ -303,22 +295,22 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
val fileDirItems = ArrayList<FileDirItem>(selectedPositions.size)
|
||||
val removeMedia = ArrayList<ThumbnailMedium>(selectedPositions.size)
|
||||
|
||||
if (thumbnailItems.size <= selectedPositions.first()) {
|
||||
if (media.size <= selectedPositions.first()) {
|
||||
finishActMode()
|
||||
return
|
||||
}
|
||||
|
||||
val SAFPath = (thumbnailItems[selectedPositions.first()] as ThumbnailMedium).path
|
||||
val SAFPath = (media[selectedPositions.first()] as ThumbnailMedium).path
|
||||
activity.handleSAFDialog(SAFPath) {
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val thumbnailItem = thumbnailItems[it]
|
||||
val thumbnailItem = media[it]
|
||||
if (thumbnailItem is ThumbnailMedium) {
|
||||
fileDirItems.add(FileDirItem(thumbnailItem.path, thumbnailItem.name))
|
||||
removeMedia.add(thumbnailItem)
|
||||
}
|
||||
}
|
||||
|
||||
thumbnailItems.removeAll(removeMedia)
|
||||
media.removeAll(removeMedia)
|
||||
listener?.tryDeleteFiles(fileDirItems)
|
||||
removeSelectedItems()
|
||||
}
|
||||
|
@ -327,19 +319,18 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
private fun getSelectedMedia(): List<ThumbnailMedium> {
|
||||
val selectedMedia = ArrayList<ThumbnailMedium>(selectedPositions.size)
|
||||
selectedPositions.forEach {
|
||||
selectedMedia.add(thumbnailItems[it] as ThumbnailMedium)
|
||||
selectedMedia.add(media[it] as ThumbnailMedium)
|
||||
}
|
||||
return selectedMedia
|
||||
}
|
||||
|
||||
private fun getSelectedPaths() = getSelectedMedia().map { it.path } as ArrayList<String>
|
||||
|
||||
fun updateMedia(newMedia: ArrayList<Medium>) {
|
||||
if (newMedia.hashCode() != currentMediaHash || currentGrouping != config.getFolderGrouping(path)) {
|
||||
fun updateMedia(newMedia: ArrayList<ThumbnailItem>) {
|
||||
if (newMedia.hashCode() != currentMediaHash) {
|
||||
currentMediaHash = newMedia.hashCode()
|
||||
Handler().postDelayed({
|
||||
media = newMedia
|
||||
groupMedia()
|
||||
enableInstantLoad()
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
|
@ -376,69 +367,7 @@ class MediaAdapter(activity: BaseSimpleActivity, var media: MutableList<Medium>,
|
|||
}, INSTANT_LOAD_DURATION)
|
||||
}
|
||||
|
||||
private fun groupMedia() {
|
||||
currentGrouping = config.getFolderGrouping(path)
|
||||
if (currentGrouping and GROUP_BY_NONE != 0) {
|
||||
return
|
||||
}
|
||||
|
||||
mediumGroups.clear()
|
||||
media.forEach {
|
||||
val key = it.getGroupingKey(currentGrouping)
|
||||
if (!mediumGroups.containsKey(key)) {
|
||||
mediumGroups[key] = ArrayList()
|
||||
}
|
||||
mediumGroups[key]!!.add(it)
|
||||
}
|
||||
|
||||
val sortDescending = currentGrouping and GROUP_DESCENDING != 0
|
||||
val sorted = mediumGroups.toSortedMap(if (sortDescending) compareByDescending { it } else compareBy { it })
|
||||
mediumGroups.clear()
|
||||
sorted.forEach { key, value ->
|
||||
mediumGroups[key] = value
|
||||
}
|
||||
|
||||
thumbnailItems.clear()
|
||||
for ((key, value) in mediumGroups) {
|
||||
thumbnailItems.add(ThumbnailSection(getFormattedKey(key, currentGrouping)))
|
||||
value.forEach {
|
||||
val thumbnailMedium = ThumbnailMedium(it.name, it.path, it.parentPath, it.modified, it.taken, it.size, it.type, it.isFavorite)
|
||||
thumbnailItems.add(thumbnailMedium)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFormattedKey(key: String, grouping: Int): String {
|
||||
return when {
|
||||
grouping and GROUP_BY_LAST_MODIFIED != 0 || grouping and GROUP_BY_DATE_TAKEN != 0 -> formatDate(key)
|
||||
grouping and GROUP_BY_FILE_TYPE != 0 -> getFileTypeString(key)
|
||||
grouping and GROUP_BY_EXTENSION != 0 -> key.toUpperCase()
|
||||
grouping and GROUP_BY_FOLDER != 0 -> activity.humanizePath(key)
|
||||
else -> key
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDate(timestamp: String): String {
|
||||
return if (timestamp.areDigitsOnly()) {
|
||||
val cal = Calendar.getInstance(Locale.ENGLISH)
|
||||
cal.timeInMillis = timestamp.toLong()
|
||||
DateFormat.format("dd MMM yyyy", cal).toString()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFileTypeString(key: String): String {
|
||||
val stringId = when (key.toInt()) {
|
||||
TYPE_IMAGES -> R.string.images
|
||||
TYPE_VIDEOS -> R.string.videos
|
||||
TYPE_GIFS -> R.string.gifs
|
||||
else -> R.string.raw_images
|
||||
}
|
||||
return activity.getString(stringId)
|
||||
}
|
||||
|
||||
fun getItemBubbleText(position: Int, sorting: Int) = (thumbnailItems[position] as? ThumbnailMedium)?.getBubbleText(sorting)
|
||||
fun getItemBubbleText(position: Int, sorting: Int) = (media[position] as? ThumbnailMedium)?.getBubbleText(sorting)
|
||||
|
||||
private fun setupThumbnailMedium(view: View, medium: ThumbnailMedium) {
|
||||
view.apply {
|
||||
|
|
|
@ -12,13 +12,15 @@ import com.simplemobiletools.gallery.adapters.MediaAdapter
|
|||
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getCachedMedia
|
||||
import com.simplemobiletools.gallery.helpers.MediaFetcher
|
||||
import com.simplemobiletools.gallery.helpers.VIEW_TYPE_GRID
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import kotlinx.android.synthetic.main.dialog_medium_picker.view.*
|
||||
|
||||
class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val callback: (path: String) -> Unit) {
|
||||
var dialog: AlertDialog
|
||||
var shownMedia = ArrayList<Medium>()
|
||||
var shownMedia = ArrayList<ThumbnailItem>()
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_medium_picker, null)
|
||||
var isGridViewType = activity.config.viewTypeFiles == VIEW_TYPE_GRID
|
||||
|
||||
|
@ -31,7 +33,7 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
dialog = AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setNeutralButton(R.string.other_folder, { dialogInterface, i -> showOtherFolder() })
|
||||
.setNeutralButton(R.string.other_folder) { dialogInterface, i -> showOtherFolder() }
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this, R.string.select_photo)
|
||||
}
|
||||
|
@ -61,8 +63,8 @@ class PickMediumDialog(val activity: BaseSimpleActivity, val path: String, val c
|
|||
if (media.hashCode() == shownMedia.hashCode())
|
||||
return
|
||||
|
||||
shownMedia = media
|
||||
val adapter = MediaAdapter(activity, media, null, true, false, view.media_grid, null, path) {
|
||||
shownMedia = MediaFetcher(activity).groupMedia(media, path)
|
||||
val adapter = MediaAdapter(activity, shownMedia, null, true, false, view.media_grid, null) {
|
||||
callback((it as Medium).path)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
|
|
@ -4,14 +4,20 @@ import android.content.Context
|
|||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import android.text.format.DateFormat
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.config
|
||||
import com.simplemobiletools.gallery.extensions.getDistinctPath
|
||||
import com.simplemobiletools.gallery.extensions.getOTGFolderChildren
|
||||
import com.simplemobiletools.gallery.extensions.shouldFolderBeVisible
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailItem
|
||||
import com.simplemobiletools.gallery.models.ThumbnailMedium
|
||||
import com.simplemobiletools.gallery.models.ThumbnailSection
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class MediaFetcher(val context: Context) {
|
||||
var shouldStop = false
|
||||
|
@ -329,4 +335,72 @@ class MediaFetcher(val context: Context) {
|
|||
result
|
||||
})
|
||||
}
|
||||
|
||||
fun groupMedia(media: ArrayList<Medium>, path: String): ArrayList<ThumbnailItem> {
|
||||
val thumbnailItems = ArrayList<ThumbnailItem>()
|
||||
val mediumGroups = LinkedHashMap<String, ArrayList<Medium>>()
|
||||
val currentGrouping = context.config.getFolderGrouping(path)
|
||||
if (currentGrouping and GROUP_BY_NONE != 0) {
|
||||
media.forEach {
|
||||
val thumbnailMedium = ThumbnailMedium(it.name, it.path, it.parentPath, it.modified, it.taken, it.size, it.type, it.isFavorite)
|
||||
thumbnailItems.add(thumbnailMedium)
|
||||
}
|
||||
return thumbnailItems
|
||||
}
|
||||
|
||||
media.forEach {
|
||||
val key = it.getGroupingKey(currentGrouping)
|
||||
if (!mediumGroups.containsKey(key)) {
|
||||
mediumGroups[key] = ArrayList()
|
||||
}
|
||||
mediumGroups[key]!!.add(it)
|
||||
}
|
||||
|
||||
val sortDescending = currentGrouping and GROUP_DESCENDING != 0
|
||||
val sorted = mediumGroups.toSortedMap(if (sortDescending) compareByDescending { it } else compareBy { it })
|
||||
mediumGroups.clear()
|
||||
sorted.forEach { key, value ->
|
||||
mediumGroups[key] = value
|
||||
}
|
||||
|
||||
for ((key, value) in mediumGroups) {
|
||||
thumbnailItems.add(ThumbnailSection(getFormattedKey(key, currentGrouping)))
|
||||
value.forEach {
|
||||
val thumbnailMedium = ThumbnailMedium(it.name, it.path, it.parentPath, it.modified, it.taken, it.size, it.type, it.isFavorite)
|
||||
thumbnailItems.add(thumbnailMedium)
|
||||
}
|
||||
}
|
||||
|
||||
return thumbnailItems
|
||||
}
|
||||
|
||||
private fun getFormattedKey(key: String, grouping: Int): String {
|
||||
return when {
|
||||
grouping and GROUP_BY_LAST_MODIFIED != 0 || grouping and GROUP_BY_DATE_TAKEN != 0 -> formatDate(key)
|
||||
grouping and GROUP_BY_FILE_TYPE != 0 -> getFileTypeString(key)
|
||||
grouping and GROUP_BY_EXTENSION != 0 -> key.toUpperCase()
|
||||
grouping and GROUP_BY_FOLDER != 0 -> context.humanizePath(key)
|
||||
else -> key
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDate(timestamp: String): String {
|
||||
return if (timestamp.areDigitsOnly()) {
|
||||
val cal = Calendar.getInstance(Locale.ENGLISH)
|
||||
cal.timeInMillis = timestamp.toLong()
|
||||
DateFormat.format("dd MMM yyyy", cal).toString()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFileTypeString(key: String): String {
|
||||
val stringId = when (key.toInt()) {
|
||||
TYPE_IMAGES -> R.string.images
|
||||
TYPE_VIDEOS -> R.string.videos
|
||||
TYPE_GIFS -> R.string.gifs
|
||||
else -> R.string.raw_images
|
||||
}
|
||||
return context.getString(stringId)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue