mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Updated JavaDocs in UploadWorker, Fixed Test cases
This commit is contained in:
parent
1c6e533c1a
commit
6813476c86
4 changed files with 80 additions and 15 deletions
|
|
@ -21,7 +21,6 @@ import fr.free.nrw.commons.media.MediaClient
|
||||||
import fr.free.nrw.commons.upload.StashUploadState
|
import fr.free.nrw.commons.upload.StashUploadState
|
||||||
import fr.free.nrw.commons.upload.UploadClient
|
import fr.free.nrw.commons.upload.UploadClient
|
||||||
import fr.free.nrw.commons.upload.UploadResult
|
import fr.free.nrw.commons.upload.UploadResult
|
||||||
import fr.free.nrw.commons.utils.ViewUtil
|
|
||||||
import fr.free.nrw.commons.wikidata.WikidataEditService
|
import fr.free.nrw.commons.wikidata.WikidataEditService
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.asFlow
|
import kotlinx.coroutines.flow.asFlow
|
||||||
|
|
@ -29,8 +28,8 @@ import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.lang.Exception
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.regex.Pattern
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
|
@ -184,23 +183,34 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
}
|
}
|
||||||
}.collect()
|
}.collect()
|
||||||
|
|
||||||
|
//Dismiss the global notification
|
||||||
notificationManager?.cancel(
|
notificationManager?.cancel(
|
||||||
PROCESSING_UPLOADS_NOTIFICATION_TAG,
|
PROCESSING_UPLOADS_NOTIFICATION_TAG,
|
||||||
PROCESSING_UPLOADS_NOTIFICATION_ID
|
PROCESSING_UPLOADS_NOTIFICATION_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//No need to keep looking if the limited connection mode is on,
|
||||||
|
//If the user toggles it, the work manager will be started again
|
||||||
if(isLimitedConnectionModeEnabled()){
|
if(isLimitedConnectionModeEnabled()){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//TODO make this smart, think of handling retries in the future
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true is the limited connection mode is enabled
|
||||||
|
*/
|
||||||
private fun isLimitedConnectionModeEnabled(): Boolean {
|
private fun isLimitedConnectionModeEnabled(): Boolean {
|
||||||
return sessionManager.getPreference(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED)
|
return sessionManager.getPreference(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload the contribution
|
||||||
|
* @param contribution
|
||||||
|
*/
|
||||||
@SuppressLint("StringFormatInvalid")
|
@SuppressLint("StringFormatInvalid")
|
||||||
private suspend fun uploadContribution(contribution: Contribution) {
|
private suspend fun uploadContribution(contribution: Contribution) {
|
||||||
if (contribution.localUri == null || contribution.localUri.path == null) {
|
if (contribution.localUri == null || contribution.localUri.path == null) {
|
||||||
|
|
@ -211,7 +221,8 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
val displayTitle = contribution.media.displayTitle
|
val displayTitle = contribution.media.displayTitle
|
||||||
|
|
||||||
currentNotificationTag = contribution.localUri.toString()
|
currentNotificationTag = contribution.localUri.toString()
|
||||||
currentNotificationID = contribution.hashCode()
|
currentNotificationID =
|
||||||
|
(contribution.localUri.toString() + contribution.media.filename).hashCode()
|
||||||
|
|
||||||
curentNotification
|
curentNotification
|
||||||
getNotificationBuilder(CommonsApplication.NOTIFICATION_CHANNEL_ID_ALL)!!
|
getNotificationBuilder(CommonsApplication.NOTIFICATION_CHANNEL_ID_ALL)!!
|
||||||
|
|
@ -239,18 +250,21 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
//Upload the file to stash
|
||||||
val stashUploadResult = uploadClient.uploadFileToStash(
|
val stashUploadResult = uploadClient.uploadFileToStash(
|
||||||
appContext, filename, contribution, notificationProgressUpdater
|
appContext, filename, contribution, notificationProgressUpdater
|
||||||
).blockingSingle()
|
).blockingSingle()
|
||||||
|
|
||||||
when (stashUploadResult.state) {
|
when (stashUploadResult.state) {
|
||||||
StashUploadState.SUCCESS -> {
|
StashUploadState.SUCCESS -> {
|
||||||
|
//If the stash upload succeeds
|
||||||
Timber.d("Upload to stash success for fileName: $filename")
|
Timber.d("Upload to stash success for fileName: $filename")
|
||||||
Timber.d("Ensure uniqueness of filename");
|
Timber.d("Ensure uniqueness of filename");
|
||||||
val uniqueFileName = findUniqueFileName(filename!!)
|
val uniqueFileName = findUniqueFileName(filename!!)
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
//Upload the file from stash
|
||||||
val uploadResult = uploadClient.uploadFileFromStash(
|
val uploadResult = uploadClient.uploadFileFromStash(
|
||||||
contribution, uniqueFileName, stashUploadResult.fileKey
|
contribution, uniqueFileName, stashUploadResult.fileKey
|
||||||
).blockingSingle()
|
).blockingSingle()
|
||||||
|
|
@ -306,6 +320,9 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the WikiData Edit, if applicable
|
||||||
|
*/
|
||||||
private suspend fun makeWikiDataEdit(uploadResult: UploadResult, contribution: Contribution) {
|
private suspend fun makeWikiDataEdit(uploadResult: UploadResult, contribution: Contribution) {
|
||||||
wikidataEditService.addDepictionsAndCaptions(uploadResult, contribution)
|
wikidataEditService.addDepictionsAndCaptions(uploadResult, contribution)
|
||||||
val wikiDataPlace = contribution.wikidataPlace
|
val wikiDataPlace = contribution.wikidataPlace
|
||||||
|
|
@ -351,10 +368,54 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
.blockingAwait()
|
.blockingAwait()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findUniqueFileName(filename: String): String {
|
private fun findUniqueFileName(fileName: String): String {
|
||||||
return filename;
|
var sequenceFileName: String?
|
||||||
|
var sequenceNumber = 1
|
||||||
|
while (true) {
|
||||||
|
sequenceFileName = if (sequenceNumber == 1) {
|
||||||
|
fileName
|
||||||
|
} else {
|
||||||
|
if (fileName.indexOf('.') == -1) {
|
||||||
|
"$fileName $sequenceNumber"
|
||||||
|
} else {
|
||||||
|
val regex =
|
||||||
|
Pattern.compile("^(.*)(\\..+?)$")
|
||||||
|
val regexMatcher = regex.matcher(fileName)
|
||||||
|
regexMatcher.replaceAll("$1 $sequenceNumber$2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mediaClient.checkPageExistsUsingTitle(
|
||||||
|
String.format(
|
||||||
|
"File:%s",
|
||||||
|
sequenceFileName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.blockingGet()
|
||||||
|
&& !isThereAnUnfinishedUploadWithFileName(sequenceFileName!!)
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sequenceNumber++
|
||||||
|
}
|
||||||
|
return sequenceFileName!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To remove possibilities of overriding already uploaded files partially/fully, lets
|
||||||
|
* make sure we don't already have a file with the same same
|
||||||
|
*/
|
||||||
|
private fun isThereAnUnfinishedUploadWithFileName(fileName: String): Boolean {
|
||||||
|
val contributionWithTitle = contributionDao.getContributionWithTitle(fileName)
|
||||||
|
if (contributionWithTitle.isEmpty()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify that the current upload has succeeded
|
||||||
|
* @param contribution
|
||||||
|
*/
|
||||||
@SuppressLint("StringFormatInvalid")
|
@SuppressLint("StringFormatInvalid")
|
||||||
private fun showSuccessNotification(contribution: Contribution) {
|
private fun showSuccessNotification(contribution: Contribution) {
|
||||||
val displayTitle = contribution.media.displayTitle
|
val displayTitle = contribution.media.displayTitle
|
||||||
|
|
@ -375,6 +436,10 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
contributionDao.save(contribution).blockingAwait()
|
contributionDao.save(contribution).blockingAwait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify that the current upload has failed
|
||||||
|
* @param contribution
|
||||||
|
*/
|
||||||
@SuppressLint("StringFormatInvalid")
|
@SuppressLint("StringFormatInvalid")
|
||||||
private fun showFailedNotification(contribution: Contribution) {
|
private fun showFailedNotification(contribution: Contribution) {
|
||||||
val displayTitle = contribution.media.displayTitle
|
val displayTitle = contribution.media.displayTitle
|
||||||
|
|
@ -393,6 +458,10 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) :
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify that the current upload is paused
|
||||||
|
* @param contribution
|
||||||
|
*/
|
||||||
private fun showPausedNotification(contribution: Contribution) {
|
private fun showPausedNotification(contribution: Contribution) {
|
||||||
val displayTitle = contribution.media.displayTitle
|
val displayTitle = contribution.media.displayTitle
|
||||||
curentNotification.setContentTitle(
|
curentNotification.setContentTitle(
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ class BookmarkPictureDaoTest {
|
||||||
whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(createCursor(1))
|
whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(createCursor(1))
|
||||||
|
|
||||||
assertFalse(testObject.updateBookmark(exampleBookmark))
|
assertFalse(testObject.updateBookmark(exampleBookmark))
|
||||||
verify(client).delete(eq(exampleBookmark.contentUri), isNull(), isNull())
|
verify(client).delete(eq(exampleBookmark.contentUri!!), isNull(), isNull())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ class RecentSearchesDaoTest {
|
||||||
|
|
||||||
testObject.save(recentSearch)
|
testObject.save(recentSearch)
|
||||||
|
|
||||||
verify(client).update(eq(recentSearch.contentUri), captor.capture(), isNull(), isNull())
|
verify(client).update(eq(recentSearch.contentUri!!), captor.capture(), isNull(), isNull())
|
||||||
captor.firstValue.let { cv ->
|
captor.firstValue.let { cv ->
|
||||||
assertEquals(2, cv.size())
|
assertEquals(2, cv.size())
|
||||||
assertEquals(recentSearch.query, cv.getAsString(COLUMN_NAME))
|
assertEquals(recentSearch.query, cv.getAsString(COLUMN_NAME))
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,24 @@
|
||||||
package fr.free.nrw.commons.upload
|
package fr.free.nrw.commons.upload
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.nhaarman.mockitokotlin2.mock
|
import com.nhaarman.mockitokotlin2.mock
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
import fr.free.nrw.commons.auth.SessionManager
|
|
||||||
import fr.free.nrw.commons.contributions.Contribution
|
import fr.free.nrw.commons.contributions.Contribution
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.InjectMocks
|
import org.mockito.InjectMocks
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.`when`
|
|
||||||
import org.mockito.Mockito.mock
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
class UploadControllerTest {
|
class UploadControllerTest {
|
||||||
|
|
||||||
@Mock
|
|
||||||
internal var sessionManager: SessionManager? = null
|
|
||||||
@Mock
|
@Mock
|
||||||
internal var context: Context? = null
|
internal var context: Context? = null
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
internal var prefs: JsonKvStore? = null
|
internal lateinit var contentResolver: ContentResolver
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
var uploadController: UploadController? = null
|
var uploadController: UploadController? = null
|
||||||
|
|
@ -47,6 +42,7 @@ class UploadControllerTest {
|
||||||
val media = mock<Media>()
|
val media = mock<Media>()
|
||||||
whenever(contribution.media).thenReturn(media)
|
whenever(contribution.media).thenReturn(media)
|
||||||
whenever(media.author).thenReturn("Creator")
|
whenever(media.author).thenReturn("Creator")
|
||||||
|
whenever(context?.contentResolver).thenReturn(contentResolver)
|
||||||
uploadController!!.prepareMedia(contribution)
|
uploadController!!.prepareMedia(contribution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue