mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
update UI states and refactor code
Also, add repository as Single Source of Truth for performing operations on images
This commit is contained in:
parent
443e713955
commit
e611cbc86f
14 changed files with 262 additions and 49 deletions
|
|
@ -0,0 +1,29 @@
|
|||
package fr.free.nrw.commons.customselector.data
|
||||
|
||||
import fr.free.nrw.commons.customselector.database.NotForUploadStatus
|
||||
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
|
||||
import fr.free.nrw.commons.customselector.domain.ImageRepository
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class ImageRepositoryImpl @Inject constructor(
|
||||
private val mediaReader: MediaReader,
|
||||
private val notForUploadStatusDao: NotForUploadStatusDao
|
||||
): ImageRepository {
|
||||
override suspend fun getImagesFromDevice(): Flow<Image> {
|
||||
return mediaReader.getImages()
|
||||
}
|
||||
|
||||
override suspend fun markAsNotForUpload(imageSHA: String) {
|
||||
notForUploadStatusDao.insert(NotForUploadStatus(imageSHA))
|
||||
}
|
||||
|
||||
override suspend fun unmarkAsNotForUpload(imageSHA: String) {
|
||||
notForUploadStatusDao.deleteWithImageSHA1(imageSHA)
|
||||
}
|
||||
|
||||
override suspend fun isNotForUpload(imageSHA: String): Boolean {
|
||||
return notForUploadStatusDao.find(imageSHA) > 0
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package fr.free.nrw.commons.customselector.domain
|
||||
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ImageRepository {
|
||||
|
||||
suspend fun getImagesFromDevice(): Flow<Image>
|
||||
|
||||
suspend fun markAsNotForUpload(imageSHA: String)
|
||||
|
||||
suspend fun unmarkAsNotForUpload(imageSHA: String)
|
||||
|
||||
suspend fun isNotForUpload(imageSHA: String): Boolean
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package fr.free.nrw.commons.customselector.domain.use_case
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import fr.free.nrw.commons.customselector.ui.selector.ImageLoader
|
||||
import fr.free.nrw.commons.filepicker.PickedFiles
|
||||
import fr.free.nrw.commons.media.MediaClient
|
||||
import fr.free.nrw.commons.upload.FileProcessor
|
||||
import fr.free.nrw.commons.upload.FileUtilsWrapper
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okio.FileNotFoundException
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
|
||||
class ImageUseCase @Inject constructor(
|
||||
private val fileUtilsWrapper: FileUtilsWrapper,
|
||||
private val fileProcessor: FileProcessor,
|
||||
private val mediaClient: MediaClient,
|
||||
private val context: Context
|
||||
) {
|
||||
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||
|
||||
/**
|
||||
* Retrieves the SHA1 hash of an image from its URI.
|
||||
*
|
||||
* @param uri The URI of the image.
|
||||
* @return The SHA1 hash of the image, or an empty string if the image is not found.
|
||||
*/
|
||||
suspend fun getImageSHA1(uri: Uri): String = withContext(ioDispatcher) {
|
||||
try {
|
||||
val inputStream = context.contentResolver.openInputStream(uri)
|
||||
fileUtilsWrapper.getSHA1(inputStream)
|
||||
} catch (e: FileNotFoundException) {
|
||||
Timber.e(e)
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a modified SHA1 hash of an image after redacting sensitive EXIF tags.
|
||||
*
|
||||
* @param imageUri The URI of the image to process.
|
||||
* @return The modified SHA1 hash of the image.
|
||||
*/
|
||||
suspend fun generateModifiedSHA1(imageUri: Uri): String = withContext(ioDispatcher) {
|
||||
val uploadableFile = PickedFiles.pickedExistingPicture(context, imageUri)
|
||||
val exifInterface: ExifInterface? = try {
|
||||
ExifInterface(uploadableFile.file!!)
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
null
|
||||
}
|
||||
fileProcessor.redactExifTags(exifInterface, fileProcessor.getExifTagsToRedact())
|
||||
|
||||
val sha1 = fileUtilsWrapper.getSHA1(
|
||||
fileUtilsWrapper.getFileInputStream(uploadableFile.filePath))
|
||||
uploadableFile.file.delete()
|
||||
sha1
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file with the given SHA1 hash exists on Wikimedia Commons.
|
||||
*
|
||||
* @param sha1 The SHA1 hash of the file to check.
|
||||
* @return An ImageLoader.Result indicating the existence of the file on Commons.
|
||||
*/
|
||||
suspend fun checkWhetherFileExistsOnCommonsUsingSHA1(
|
||||
sha1: String
|
||||
): ImageLoader.Result = withContext(ioDispatcher) {
|
||||
return@withContext try {
|
||||
if (mediaClient.checkFileExistsUsingSha(sha1).blockingGet()) {
|
||||
ImageLoader.Result.TRUE
|
||||
} else {
|
||||
ImageLoader.Result.FALSE
|
||||
}
|
||||
} catch (e: UnknownHostException) {
|
||||
Timber.e(e, "Network Connection Error")
|
||||
ImageLoader.Result.ERROR
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
ImageLoader.Result.ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,12 +56,14 @@ import fr.free.nrw.commons.R
|
|||
import fr.free.nrw.commons.customselector.ui.components.CustomSelectorBottomBar
|
||||
import fr.free.nrw.commons.customselector.ui.components.CustomSelectorTopBar
|
||||
import fr.free.nrw.commons.customselector.ui.components.PartialStorageAccessDialog
|
||||
import fr.free.nrw.commons.customselector.ui.states.CustomSelectorUiState
|
||||
import fr.free.nrw.commons.customselector.ui.states.ImageUiState
|
||||
import fr.free.nrw.commons.ui.theme.CommonsTheme
|
||||
|
||||
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
|
||||
@Composable
|
||||
fun CustomSelectorScreen(
|
||||
uiState: CustomSelectorState,
|
||||
uiState: CustomSelectorUiState,
|
||||
onEvent: (CustomSelectorEvent)-> Unit,
|
||||
selectedImageIds: ()-> Set<Long>,
|
||||
onViewImage: (id: Long)-> Unit,
|
||||
|
|
@ -112,7 +114,7 @@ fun CustomSelectorScreen(
|
|||
|
||||
@Composable
|
||||
fun FoldersPane(
|
||||
uiState: CustomSelectorState,
|
||||
uiState: CustomSelectorUiState,
|
||||
onFolderClick: (Folder)-> Unit,
|
||||
onUnselectAll: ()-> Unit,
|
||||
adaptiveInfo: WindowAdaptiveInfo,
|
||||
|
|
@ -270,7 +272,7 @@ private fun FolderItemPreview() {
|
|||
private fun CustomSelectorScreenPreview() {
|
||||
CommonsTheme {
|
||||
CustomSelectorScreen(
|
||||
uiState = CustomSelectorState(),
|
||||
uiState = CustomSelectorUiState(),
|
||||
onViewImage = { },
|
||||
onEvent = { },
|
||||
selectedImageIds = { emptySet() },
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
package fr.free.nrw.commons.customselector.ui.screens
|
||||
|
||||
import fr.free.nrw.commons.customselector.model.Image
|
||||
|
||||
data class CustomSelectorState(
|
||||
val isLoading: Boolean = false,
|
||||
val folders: List<Folder> = emptyList(),
|
||||
val filteredImages: List<Image> = emptyList(),
|
||||
val selectedImageIds: Set<Long> = emptySet()
|
||||
) {
|
||||
val inSelectionMode: Boolean
|
||||
get() = selectedImageIds.isNotEmpty()
|
||||
}
|
||||
|
|
@ -1,36 +1,55 @@
|
|||
package fr.free.nrw.commons.customselector.ui.screens
|
||||
|
||||
import android.util.Log
|
||||
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 fr.free.nrw.commons.customselector.domain.ImageRepository
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import fr.free.nrw.commons.customselector.domain.use_case.ImageUseCase
|
||||
import fr.free.nrw.commons.customselector.ui.states.CustomSelectorUiState
|
||||
import fr.free.nrw.commons.customselector.ui.states.ImageUiState
|
||||
import fr.free.nrw.commons.customselector.ui.states.toImageUiState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class CustomSelectorViewModel(private val mediaReader: MediaReader): ViewModel() {
|
||||
typealias imageId = Long
|
||||
typealias imageSHA = String
|
||||
|
||||
private val _uiState = MutableStateFlow(CustomSelectorState())
|
||||
class CustomSelectorViewModel @Inject constructor(
|
||||
private val imageRepository: ImageRepository,
|
||||
private val imageUseCase: ImageUseCase
|
||||
): ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(CustomSelectorUiState())
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val cacheSHA1 = mutableMapOf<imageId, imageSHA>()
|
||||
|
||||
private val allImages = mutableListOf<ImageUiState>()
|
||||
private val foldersMap = mutableMapOf<Long, MutableList<Image>>()
|
||||
|
||||
init {
|
||||
_uiState.update { it.copy(isLoading = true) }
|
||||
viewModelScope.launch {
|
||||
mediaReader.getImages().collect { image->
|
||||
imageRepository.getImagesFromDevice().collect { image ->
|
||||
val bucketId = image.bucketId
|
||||
|
||||
allImages.add(image.toImageUiState())
|
||||
foldersMap.getOrPut(bucketId) { mutableListOf() }.add(image)
|
||||
}
|
||||
val foldersList = foldersMap.map { (bucketId, images)->
|
||||
val folders = foldersMap.map { (bucketId, images)->
|
||||
val firstImage = images.first()
|
||||
Folder(
|
||||
bucketId = bucketId, bucketName = firstImage.bucketName,
|
||||
preview = firstImage.uri, itemsCount = images.size
|
||||
bucketId = bucketId,
|
||||
bucketName = firstImage.bucketName,
|
||||
preview = firstImage.uri,
|
||||
itemsCount = images.size,
|
||||
images = images
|
||||
)
|
||||
}
|
||||
_uiState.update { it.copy(isLoading = false, folders = foldersList) }
|
||||
_uiState.update { it.copy(isLoading = false, folders = folders) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +57,11 @@ class CustomSelectorViewModel(private val mediaReader: MediaReader): ViewModel()
|
|||
when(e) {
|
||||
is CustomSelectorEvent.OnFolderClick -> {
|
||||
_uiState.update {
|
||||
it.copy(filteredImages = foldersMap[e.bucketId]?.toList() ?: emptyList())
|
||||
it.copy(
|
||||
filteredImages = foldersMap[e.bucketId]?.map {
|
||||
img -> img.toImageUiState()
|
||||
} ?: emptyList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package fr.free.nrw.commons.customselector.ui.screens
|
|||
|
||||
import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
|
|
@ -9,5 +10,6 @@ data class Folder(
|
|||
val bucketId: Long,
|
||||
val bucketName: String,
|
||||
val preview: Uri,
|
||||
val images: List<Image>,
|
||||
val itemsCount: Int
|
||||
): Parcelable
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
|
|
@ -54,18 +55,20 @@ import androidx.compose.ui.unit.toIntRect
|
|||
import androidx.window.core.layout.WindowWidthSizeClass
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import fr.free.nrw.commons.customselector.ui.components.CustomSelectorBottomBar
|
||||
import fr.free.nrw.commons.customselector.ui.components.CustomSelectorTopBar
|
||||
import fr.free.nrw.commons.customselector.ui.components.PartialStorageAccessDialog
|
||||
import fr.free.nrw.commons.customselector.ui.states.CustomSelectorUiState
|
||||
import fr.free.nrw.commons.customselector.ui.states.ImageUiState
|
||||
import fr.free.nrw.commons.ui.theme.CommonsTheme
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun ImagesPane(
|
||||
uiState: CustomSelectorState,
|
||||
uiState: CustomSelectorUiState,
|
||||
selectedFolder: Folder,
|
||||
selectedImages: () -> Set<Long>,
|
||||
onNavigateBack: () -> Unit,
|
||||
|
|
@ -74,7 +77,6 @@ fun ImagesPane(
|
|||
adaptiveInfo: WindowAdaptiveInfo,
|
||||
hasPartialAccess: Boolean = false
|
||||
) {
|
||||
// val inSelectionMode by remember { derivedStateOf { selectedImages().isNotEmpty() } }
|
||||
val lazyGridState = rememberLazyGridState()
|
||||
var autoScrollSpeed by remember { mutableFloatStateOf(0f) }
|
||||
val isCompatWidth by remember(adaptiveInfo.windowSizeClass) {
|
||||
|
|
@ -255,7 +257,7 @@ private fun ImageItemPreview() {
|
|||
*/
|
||||
fun Modifier.imageGridDragHandler(
|
||||
gridState: LazyGridState,
|
||||
imageList: List<Image>,
|
||||
imageList: List<ImageUiState>,
|
||||
selectedImageIds: () -> Set<Long>,
|
||||
autoScrollThreshold: Float,
|
||||
setSelectedImageIds: (Set<Long>) -> Unit,
|
||||
|
|
@ -337,7 +339,7 @@ fun Modifier.imageGridDragHandler(
|
|||
* @param pointerKey The ending index of the range.
|
||||
* @return A set of image IDs within the specified range.
|
||||
*/
|
||||
fun List<Image>.getImageIdsInRange(initialKey: Int, pointerKey: Int): Set<Long> {
|
||||
fun List<ImageUiState>.getImageIdsInRange(initialKey: Int, pointerKey: Int): Set<Long> {
|
||||
val setOfKeys = mutableSetOf<Long>()
|
||||
if (initialKey < pointerKey) {
|
||||
(initialKey..pointerKey).forEach {
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ import androidx.compose.ui.unit.IntSize
|
|||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import fr.free.nrw.commons.customselector.ui.states.ImageUiState
|
||||
import kotlin.math.abs
|
||||
|
||||
@Composable
|
||||
fun ViewImageScreen(
|
||||
currentImageIndex: Int,
|
||||
imageList: List<Image>,
|
||||
imageList: List<ImageUiState>,
|
||||
) {
|
||||
var imageScale by remember { mutableFloatStateOf(1f) }
|
||||
var imageOffset by remember { mutableStateOf(Offset.Zero) }
|
||||
|
|
|
|||
|
|
@ -27,21 +27,20 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.customselector.data.MediaReader
|
||||
import fr.free.nrw.commons.customselector.database.NotForUploadStatus
|
||||
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import fr.free.nrw.commons.customselector.helper.CustomSelectorConstants
|
||||
import fr.free.nrw.commons.customselector.helper.FolderDeletionHelper
|
||||
import fr.free.nrw.commons.customselector.listeners.FolderClickListener
|
||||
import fr.free.nrw.commons.customselector.listeners.ImageSelectListener
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
import fr.free.nrw.commons.customselector.ui.screens.CustomSelectorScreen
|
||||
import fr.free.nrw.commons.customselector.ui.screens.ViewImageScreen
|
||||
import fr.free.nrw.commons.customselector.utils.CustomSelectorViewModelFactory
|
||||
import fr.free.nrw.commons.databinding.ActivityCustomSelectorBinding
|
||||
import fr.free.nrw.commons.databinding.CustomSelectorBottomLayoutBinding
|
||||
import fr.free.nrw.commons.databinding.CustomSelectorToolbarBinding
|
||||
|
|
@ -191,17 +190,11 @@ class CustomSelectorActivity :
|
|||
// setContentView(view)
|
||||
|
||||
prefs = applicationContext.getSharedPreferences("CustomSelector", MODE_PRIVATE)
|
||||
viewModel =
|
||||
ViewModelProvider(this, customSelectorViewModelFactory).get(
|
||||
CustomSelectorViewModel::class.java,
|
||||
)
|
||||
|
||||
val mediaReader = MediaReader(this)
|
||||
|
||||
setContent {
|
||||
val csViewModel = viewModel<fr.free.nrw.commons.customselector.ui.screens.CustomSelectorViewModel> {
|
||||
fr.free.nrw.commons.customselector.ui.screens.CustomSelectorViewModel(mediaReader)
|
||||
}
|
||||
val csViewModel = ViewModelProvider(this, customSelectorViewModelFactory).get(
|
||||
fr.free.nrw.commons.customselector.ui.screens.CustomSelectorViewModel::class.java
|
||||
)
|
||||
|
||||
val uiState by csViewModel.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
|
|
@ -265,7 +258,7 @@ class CustomSelectorActivity :
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
fetchData()
|
||||
// fetchData()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package fr.free.nrw.commons.customselector.ui.states
|
||||
|
||||
import fr.free.nrw.commons.customselector.ui.screens.Folder
|
||||
import fr.free.nrw.commons.customselector.ui.screens.imageId
|
||||
|
||||
typealias isNotForUpload = Boolean
|
||||
|
||||
data class CustomSelectorUiState(
|
||||
val isLoading: Boolean = true,
|
||||
val folders: List<Folder> = emptyList(),
|
||||
val filteredImages: List<ImageUiState> = emptyList(),
|
||||
val selectedImageIds: Set<Long> = emptySet(),
|
||||
val imagesNotForUpload: Map<imageId, isNotForUpload> = emptyMap()
|
||||
) {
|
||||
val inSelectionMode: Boolean
|
||||
get() = selectedImageIds.isNotEmpty()
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package fr.free.nrw.commons.customselector.ui.states
|
||||
|
||||
import android.net.Uri
|
||||
import fr.free.nrw.commons.customselector.domain.model.Image
|
||||
|
||||
data class ImageUiState(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val uri: Uri,
|
||||
val bucketId: Long,
|
||||
val isNotForUpload: Boolean = false,
|
||||
val isUploaded: Boolean = false
|
||||
)
|
||||
|
||||
fun Image.toImageUiState() = ImageUiState(
|
||||
id = id,
|
||||
name = name,
|
||||
uri = uri,
|
||||
bucketId = bucketId
|
||||
)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package fr.free.nrw.commons.customselector.utils
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import fr.free.nrw.commons.customselector.domain.ImageRepository
|
||||
import fr.free.nrw.commons.customselector.domain.use_case.ImageUseCase
|
||||
import fr.free.nrw.commons.customselector.ui.screens.CustomSelectorViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class CustomSelectorViewModelFactory @Inject constructor(
|
||||
private val imageRepository: ImageRepository,
|
||||
private val imageUseCase: ImageUseCase
|
||||
): ViewModelProvider.Factory {
|
||||
override fun <CustomSelectorViewModel : ViewModel> create(
|
||||
modelClass: Class<CustomSelectorViewModel>
|
||||
): CustomSelectorViewModel {
|
||||
return CustomSelectorViewModel(
|
||||
imageRepository, imageUseCase
|
||||
) as CustomSelectorViewModel
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,12 @@ import fr.free.nrw.commons.R;
|
|||
import fr.free.nrw.commons.auth.AccountUtil;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||
import fr.free.nrw.commons.customselector.data.ImageRepositoryImpl;
|
||||
import fr.free.nrw.commons.customselector.data.MediaReader;
|
||||
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao;
|
||||
import fr.free.nrw.commons.customselector.database.UploadedStatusDao;
|
||||
import fr.free.nrw.commons.customselector.domain.ImageRepository;
|
||||
import fr.free.nrw.commons.customselector.domain.use_case.ImageUseCase;
|
||||
import fr.free.nrw.commons.customselector.ui.selector.ImageFileLoader;
|
||||
import fr.free.nrw.commons.data.DBOpenHelper;
|
||||
import fr.free.nrw.commons.db.AppDatabase;
|
||||
|
|
@ -317,4 +321,13 @@ public class CommonsApplicationModule {
|
|||
public ContentResolver providesContentResolver(Context context){
|
||||
return context.getContentResolver();
|
||||
}
|
||||
|
||||
@Provides
|
||||
public ImageRepository providesImageRepository(
|
||||
MediaReader mediaReader,
|
||||
NotForUploadStatusDao notForUploadStatusDao,
|
||||
ImageUseCase imageUseCase
|
||||
) {
|
||||
return new ImageRepositoryImpl(mediaReader, notForUploadStatusDao);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue