From 9f9938a0b7e7f0205422d4f97d33364effcea785 Mon Sep 17 00:00:00 2001 From: Sujal-Gupta-SG Date: Sat, 4 Jan 2025 18:20:06 +0530 Subject: [PATCH] Fixed #6084 --- .../ContributionsListPresenter.java | 34 +++++++++++------ .../ContributionsRemoteDataSource.kt | 37 ++++++++++++++++--- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java index a7c49c23e..c867511ab 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListPresenter.java @@ -22,7 +22,6 @@ import java.util.List; import javax.inject.Inject; import javax.inject.Named; import kotlin.Unit; -import kotlin.jvm.functions.Function0; /** * The presenter class for Contributions @@ -45,7 +44,7 @@ public class ContributionsListPresenter implements UserActionListener { // Timer for polling new contributions private Handler pollingHandler; private Runnable pollingRunnable; - private long pollingInterval = 1 * 60 * 1000L; // Poll every minute + private long pollingInterval = 24 * 60 * 60 * 1000L; // Poll every day @Inject ContributionsListPresenter( @@ -136,7 +135,7 @@ public class ContributionsListPresenter implements UserActionListener { } /** - * Start polling for new contributions every 15 minutes. + * Start polling for new contributions every 24 hour. */ private void startPollingForNewContributions() { if (pollingHandler != null) { @@ -147,7 +146,7 @@ public class ContributionsListPresenter implements UserActionListener { pollingRunnable = new Runnable() { @Override public void run() { - fetchNewContributions(); // Fetch new contributions in background + checkForNewContributions(); pollingHandler.postDelayed(this, pollingInterval); // Repeat after the interval } }; @@ -164,22 +163,33 @@ public class ContributionsListPresenter implements UserActionListener { pollingRunnable = null; } } + private String lastKnownIdentifier = null; // Declare and initialize + + /** + * Check for new contributions by comparing the latest contribution identifier. + */ + private void checkForNewContributions() { + contributionsRemoteDataSource.fetchLatestContributionIdentifier(latestIdentifier -> { + if (latestIdentifier != null && !latestIdentifier.equals(lastKnownIdentifier)) { + lastKnownIdentifier = latestIdentifier; + fetchAllContributions(); // Fetch the full list of contributions + } + return Unit.INSTANCE; // Explicitly return Unit for Kotlin compatibility + }); - public void appendContributions(List newContributions) { - if (newContributions != null && !newContributions.isEmpty()) { - existingContributions.addAll(newContributions); - liveData.postValue(existingContributions); - } } + /** * Fetch new contributions from the server and append them to the existing list. */ - private void fetchNewContributions() { - contributionsRemoteDataSource.fetchContributions(new ContributionsRemoteDataSource.LoadCallback() { + private void fetchAllContributions() { + contributionsRemoteDataSource.fetchAllContributions(new ContributionsRemoteDataSource.LoadCallback() { @Override public void onResult(List newContributions) { if (newContributions != null && !newContributions.isEmpty()) { - appendContributions(newContributions); // Add new contributions + existingContributions.clear(); + existingContributions.addAll(newContributions); + liveData.postValue(existingContributions); // Update liveData with the new list } } }); diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt index e840fe86f..a62030e90 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRemoteDataSource.kt @@ -25,14 +25,14 @@ class ContributionsRemoteDataSource params: LoadInitialParams, callback: LoadInitialCallback, ) { - fetchContributions(callback) + fetchAllContributions(callback) } override fun loadAfter( params: LoadParams, callback: LoadCallback, ) { - fetchContributions(callback) + fetchAllContributions(callback) } override fun loadBefore( @@ -46,7 +46,7 @@ class ContributionsRemoteDataSource /** * Fetches contributions using the MediaWiki API */ - public fun fetchContributions(callback: LoadCallback) { + fun fetchAllContributions(callback: LoadCallback) { if (userName.isNullOrEmpty()) { Timber.e("Failed to fetch contributions: userName is null or empty") return @@ -61,9 +61,10 @@ class ContributionsRemoteDataSource Contribution(media = it, state = Contribution.STATE_COMPLETED) } }.subscribeOn(ioThreadScheduler) - .subscribe({ - callback.onResult(it) - }) { error: Throwable -> + .subscribe({ contributions -> + // Pass the contributions to the callback + callback.onResult(contributions) + }) { error: Throwable -> Timber.e( "Failed to fetch contributions: %s", error.message, @@ -71,6 +72,30 @@ class ContributionsRemoteDataSource }, ) } + /** + * Fetches the latest contribution identifier only + */ + fun fetchLatestContributionIdentifier(callback: (String?) -> Unit) { + if (userName.isNullOrEmpty()) { + Timber.e("Failed to fetch latest contribution: userName is null or empty") + return + } + Timber.d("Fetching latest contribution identifier for user: $userName") + + compositeDisposable.add( + mediaClient.getMediaListForUser(userName!!) + .map { mediaList -> + mediaList.firstOrNull()?.pageId.toString() // Extract the first contribution's pageId + } + .subscribeOn(ioThreadScheduler) + .subscribe({ latestIdentifier -> + callback(latestIdentifier) + }) { error: Throwable -> + Timber.e("Failed to fetch latest contribution identifier: %s", error.message) + callback(null) + }, + ) + } fun dispose() { compositeDisposable.dispose()