add logic to fetch images from storage and manage in viewmodel

This commit is contained in:
Rohit Verma 2024-10-03 23:37:24 +05:30
parent 8558594ef6
commit 74cf035663
2 changed files with 130 additions and 0 deletions

View file

@ -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)
}

View file

@ -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 -> {}
}
}
}