mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Merge 72f7d12614 into 61c9de6fcc
This commit is contained in:
commit
dea782d088
3 changed files with 106 additions and 5 deletions
|
|
@ -57,6 +57,13 @@ class ContributionsPresenter @Inject internal constructor(
|
||||||
if (imageCheckResult == ImageUtils.IMAGE_OK) {
|
if (imageCheckResult == ImageUtils.IMAGE_OK) {
|
||||||
contribution.state = Contribution.STATE_QUEUED
|
contribution.state = Contribution.STATE_QUEUED
|
||||||
saveContribution(contribution)
|
saveContribution(contribution)
|
||||||
|
} else {
|
||||||
|
// For nearby uploads, if image already exists but Wikidata linking failed,
|
||||||
|
// we should retry just the Wikidata operation instead of deleting
|
||||||
|
if (contribution.wikidataPlace != null) {
|
||||||
|
Timber.d("Nearby upload: Image exists on Commons, retrying Wikidata P18 linking")
|
||||||
|
contribution.state = Contribution.STATE_QUEUED
|
||||||
|
saveContribution(contribution)
|
||||||
} else {
|
} else {
|
||||||
Timber.e("Contribution already exists")
|
Timber.e("Contribution already exists")
|
||||||
compositeDisposable!!.add(
|
compositeDisposable!!.add(
|
||||||
|
|
@ -66,6 +73,7 @@ class ContributionsPresenter @Inject internal constructor(
|
||||||
.subscribe()
|
.subscribe()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,14 +206,26 @@ class MediaClient
|
||||||
private fun mediaFromPageAndEntity(pages: List<MwQueryPage>): Single<List<Media>> =
|
private fun mediaFromPageAndEntity(pages: List<MwQueryPage>): Single<List<Media>> =
|
||||||
if (pages.isEmpty()) {
|
if (pages.isEmpty()) {
|
||||||
Single.just(emptyList())
|
Single.just(emptyList())
|
||||||
|
} else {
|
||||||
|
// If any pageId is invalid (0 or negative), avoid fetching entities like M0
|
||||||
|
// and convert using a blank entity to prevent wbgetentities no-such-entity errors.
|
||||||
|
if (pages.any { it.pageId() <= 0 }) {
|
||||||
|
Single.just(
|
||||||
|
pages.mapNotNull { page ->
|
||||||
|
page.imageInfo()?.let { imageInfo ->
|
||||||
|
mediaConverter.convert(page, Entities.Entity(), imageInfo)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" })
|
getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" })
|
||||||
.map {
|
.map {
|
||||||
pages
|
pages
|
||||||
.zip(it.entities().values)
|
.zip(it.entities().values)
|
||||||
.mapNotNull { (page, entity) ->
|
.mapNotNull { (page, entity) ->
|
||||||
page.imageInfo()?.let {
|
page.imageInfo()?.let { imageInfo ->
|
||||||
mediaConverter.convert(page, entity, it)
|
mediaConverter.convert(page, entity, imageInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ import android.content.Intent
|
||||||
import android.content.pm.ServiceInfo
|
import android.content.pm.ServiceInfo
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.multidex.BuildConfig
|
import androidx.multidex.BuildConfig
|
||||||
|
|
@ -340,6 +343,38 @@ class UploadWorker(
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Check if this is a retry for a nearby upload that already succeeded on Commons
|
||||||
|
// but failed on Wikidata - identified by having retries > 0, wikidataPlace != null,
|
||||||
|
// and non-empty filename (meaning it was previously uploaded)
|
||||||
|
if (contribution.retries > 0 && contribution.wikidataPlace != null &&
|
||||||
|
!contribution.media.filename.isNullOrEmpty()) {
|
||||||
|
|
||||||
|
Timber.d("Nearby upload retry detected - filename already exists: ${contribution.media.filename}")
|
||||||
|
|
||||||
|
// Create a minimal UploadResult directly from the saved filename
|
||||||
|
val uploadResult = UploadResult(
|
||||||
|
result = "Success",
|
||||||
|
filekey = "",
|
||||||
|
offset = 0,
|
||||||
|
filename = contribution.media.filename!!
|
||||||
|
)
|
||||||
|
|
||||||
|
// Skip the Commons upload and proceed directly to Wikidata operation
|
||||||
|
Timber.d("Skipping Commons upload, proceeding directly to Wikidata P18 linking")
|
||||||
|
try {
|
||||||
|
Timber.d("Retry: Directly attempting Wikidata P18 linking with existing filename")
|
||||||
|
makeWikiDataEdit(uploadResult, contribution)
|
||||||
|
Timber.d("Retry: Wikidata P18 linking succeeded!")
|
||||||
|
showSuccessNotification(contribution)
|
||||||
|
return
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
Timber.e(exception, "Retry: Wikidata P18 linking failed")
|
||||||
|
contribution.state = Contribution.STATE_FAILED
|
||||||
|
contributionDao.saveSynchronous(contribution)
|
||||||
|
showFailedNotification(contribution)
|
||||||
|
throw exception // Let WorkManager handle retry
|
||||||
|
}
|
||||||
|
}
|
||||||
// Upload the file to stash
|
// Upload the file to stash
|
||||||
val stashUploadResult =
|
val stashUploadResult =
|
||||||
uploadClient
|
uploadClient
|
||||||
|
|
@ -390,6 +425,12 @@ class UploadWorker(
|
||||||
Timber.d(
|
Timber.d(
|
||||||
"WikiDataEdit required, making wikidata edit",
|
"WikiDataEdit required, making wikidata edit",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Save the filename for retry in case Wikidata operation fails
|
||||||
|
Timber.d("Saving Commons filename to media: ${uploadResult.filename}")
|
||||||
|
contribution.media.filename = uploadResult.filename
|
||||||
|
contributionDao.saveSynchronous(contribution)
|
||||||
|
|
||||||
makeWikiDataEdit(uploadResult, contribution)
|
makeWikiDataEdit(uploadResult, contribution)
|
||||||
}
|
}
|
||||||
showSuccessNotification(contribution)
|
showSuccessNotification(contribution)
|
||||||
|
|
@ -467,6 +508,9 @@ class UploadWorker(
|
||||||
contributionDao.saveSynchronous(contribution)
|
contributionDao.saveSynchronous(contribution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For testing - set to true to enable 10-second delay before Wikidata operations
|
||||||
|
private val ENABLE_TESTING_DELAY = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the WikiData Edit, if applicable
|
* Make the WikiData Edit, if applicable
|
||||||
*/
|
*/
|
||||||
|
|
@ -479,6 +523,20 @@ class UploadWorker(
|
||||||
if (!contribution.hasInvalidLocation()) {
|
if (!contribution.hasInvalidLocation()) {
|
||||||
var revisionID: Long? = null
|
var revisionID: Long? = null
|
||||||
val p18WasSkipped = !wikiDataPlace.imageValue.isNullOrBlank()
|
val p18WasSkipped = !wikiDataPlace.imageValue.isNullOrBlank()
|
||||||
|
|
||||||
|
// Testing mechanism: Add 10-second delay before Wikidata operations to simulate network issues
|
||||||
|
if (ENABLE_TESTING_DELAY) {
|
||||||
|
Timber.d("TESTING: Adding 10-second delay before Wikidata operation")
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
Toast.makeText(applicationContext, "Starting Wikidata operation - testing delay", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
Thread.sleep(10000) // 10 seconds delay for testing
|
||||||
|
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
Toast.makeText(applicationContext, "Proceeding with Wikidata after delay", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!p18WasSkipped) {
|
if (!p18WasSkipped) {
|
||||||
// Only set P18 if the place does not already have a picture
|
// Only set P18 if the place does not already have a picture
|
||||||
|
|
@ -504,7 +562,19 @@ class UploadWorker(
|
||||||
// Always show success notification, whether P18 was set or skipped
|
// Always show success notification, whether P18 was set or skipped
|
||||||
showSuccessNotification(contribution)
|
showSuccessNotification(contribution)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Timber.e(exception)
|
Timber.e(exception, "Wikidata P18 linking failed")
|
||||||
|
|
||||||
|
// Mark contribution as failed so it can be retried
|
||||||
|
contribution.state = Contribution.STATE_FAILED
|
||||||
|
contributionDao.saveSynchronous(contribution)
|
||||||
|
|
||||||
|
// Show failed notification
|
||||||
|
showFailedNotification(contribution)
|
||||||
|
|
||||||
|
// Re-throw to allow WorkManager to retry
|
||||||
|
// If it's a network error, WorkManager will automatically retry
|
||||||
|
// Network errors: UnknownHostException, SocketException, SocketTimeoutException, etc.
|
||||||
|
throw exception
|
||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
|
@ -548,8 +618,16 @@ class UploadWorker(
|
||||||
private fun saveIntoUploadedStatus(contribution: Contribution) {
|
private fun saveIntoUploadedStatus(contribution: Contribution) {
|
||||||
contribution.contentUri?.let {
|
contribution.contentUri?.let {
|
||||||
val imageSha1 = contribution.imageSHA1.toString()
|
val imageSha1 = contribution.imageSHA1.toString()
|
||||||
val modifiedSha1 = fileUtilsWrapper.getSHA1(fileUtilsWrapper.getFileInputStream(contribution.localUri?.path))
|
val modifiedSha1 = try {
|
||||||
|
fileUtilsWrapper.getSHA1(
|
||||||
|
fileUtilsWrapper.getFileInputStream(contribution.localUri?.path),
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.w(e, "UploadedStatus: modified file missing/unreadable; falling back to original SHA1")
|
||||||
|
imageSha1
|
||||||
|
}
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
uploadedStatusDao.insertUploaded(
|
uploadedStatusDao.insertUploaded(
|
||||||
UploadedStatus(
|
UploadedStatus(
|
||||||
imageSha1,
|
imageSha1,
|
||||||
|
|
@ -558,6 +636,9 @@ class UploadWorker(
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.w(e, "UploadedStatus: insert failed; continuing")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue