mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-28 05:13:53 +01:00
add logic to fetch images from storage and manage in viewmodel
This commit is contained in:
parent
8558594ef6
commit
74cf035663
2 changed files with 130 additions and 0 deletions
|
|
@ -0,0 +1,70 @@
|
|||
package fr.free.nrw.commons.customselector.data
|
||||
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.MediaStore
|
||||
import android.text.format.DateFormat
|
||||
import fr.free.nrw.commons.customselector.model.Image
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
class MediaReader(private val context: Context) {
|
||||
fun getImages() = flow {
|
||||
val projection = arrayOf(
|
||||
MediaStore.Images.Media._ID,
|
||||
MediaStore.Images.Media.DISPLAY_NAME,
|
||||
MediaStore.Images.Media.DATA,
|
||||
MediaStore.Images.Media.BUCKET_ID,
|
||||
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
|
||||
MediaStore.Images.Media.DATE_ADDED,
|
||||
MediaStore.Images.Media.MIME_TYPE
|
||||
)
|
||||
val cursor = context.contentResolver.query(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
|
||||
null, null, MediaStore.Images.Media.DATE_ADDED + " DESC"
|
||||
)
|
||||
|
||||
cursor?.use {
|
||||
val idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID)
|
||||
val nameColumn = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
|
||||
val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
|
||||
val bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID)
|
||||
val bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME)
|
||||
val dateColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED)
|
||||
val mimeTypeColumn = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
|
||||
|
||||
while(cursor.moveToNext()) {
|
||||
val id = cursor.getLong(idColumn)
|
||||
val name = cursor.getString(nameColumn)
|
||||
val path = cursor.getString(dataColumn)
|
||||
val bucketId = cursor.getLong(bucketIdColumn)
|
||||
val bucketName = cursor.getString(bucketNameColumn)
|
||||
val date = cursor.getLong(dateColumn)
|
||||
val mimeType = cursor.getString(mimeTypeColumn)
|
||||
|
||||
val validMimeTypes = arrayOf(
|
||||
"image/jpeg", "image/png", "image/svg+xml", "image/gif",
|
||||
"image/tiff", "image/webp", "image/x-xcf"
|
||||
)
|
||||
// Skip the media items with unsupported MIME types
|
||||
if(mimeType.lowercase() !in validMimeTypes) continue
|
||||
|
||||
// URI to access the image
|
||||
val uri = ContentUris.withAppendedId(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id
|
||||
)
|
||||
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = date * 1000L
|
||||
val calendarDate: Date = calendar.time
|
||||
val dateFormat = DateFormat.getMediumDateFormat(context)
|
||||
val formattedDate = dateFormat.format(calendarDate)
|
||||
|
||||
emit(Image(id, name, uri, path, bucketId, bucketName, date = formattedDate))
|
||||
}
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package fr.free.nrw.commons.customselector.ui.screens
|
||||
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import fr.free.nrw.commons.customselector.data.MediaReader
|
||||
import fr.free.nrw.commons.customselector.model.Image
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class CustomSelectorViewModel(private val mediaReader: MediaReader): ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(CustomSelectorState())
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val foldersMap = mutableMapOf<Long, MutableList<Image>>()
|
||||
|
||||
private var _selectedImageIds = mutableStateListOf<Long>()
|
||||
val selectedImageIds = _selectedImageIds
|
||||
|
||||
init {
|
||||
_uiState.update { it.copy(isLoading = true) }
|
||||
viewModelScope.launch {
|
||||
mediaReader.getImages().collect { image->
|
||||
val bucketId = image.bucketId
|
||||
foldersMap.getOrPut(bucketId) { mutableListOf() }.add(image)
|
||||
}
|
||||
val foldersList = foldersMap.map { (bucketId, images)->
|
||||
val firstImage = images.first()
|
||||
Folder(
|
||||
bucketId = bucketId, bucketName = firstImage.bucketName,
|
||||
preview = firstImage.uri, itemsCount = images.size
|
||||
)
|
||||
}
|
||||
_uiState.update { it.copy(isLoading = false, folders = foldersList) }
|
||||
}
|
||||
}
|
||||
|
||||
fun onEvent(e: CustomSelectorEvent) {
|
||||
when(e) {
|
||||
is CustomSelectorEvent.OnFolderClick-> {
|
||||
_uiState.update {
|
||||
it.copy(filteredImages = foldersMap[e.bucketId]?.toList() ?: emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
is CustomSelectorEvent.OnImageSelect -> {
|
||||
if(_selectedImageIds.contains(e.imageId)) {
|
||||
_selectedImageIds.remove(e.imageId)
|
||||
} else {
|
||||
_selectedImageIds.add(e.imageId)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue