diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/SocialMediaRepository.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/SocialMediaRepository.kt index 158bda0a93..1d5c927f0f 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/SocialMediaRepository.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/repository/SocialMediaRepository.kt @@ -21,6 +21,7 @@ import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject import java.util.EnumMap import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicInteger import java.util.function.Consumer import javax.inject.Inject import javax.inject.Singleton @@ -102,6 +103,14 @@ constructor(appDatabase: AppDatabase, application: Application) { return getLaoChirps(laoId).reactionByChirpId[chirpId] ?: emptySet() } + fun queryMoreChirps(laoId: String) { + getLaoChirps(laoId).queryMoreChirps() + } + + fun canQueryMoreChirps(laoId: String): Boolean { + return !getLaoChirps(laoId).isEndOfChirps() + } + /** * @param laoId of the lao we want to observe the chirp list * @return an observable set of message ids whose correspond to the set of chirp published on the @@ -132,7 +141,6 @@ constructor(appDatabase: AppDatabase, application: Application) { { err: Throwable -> Timber.tag(TAG).e(err, "Error in persisting reaction %s", reaction.id) })) - // Retrieve Lao data and add the reaction to it return getLaoChirps(laoId).addReaction(reaction) } @@ -171,6 +179,11 @@ constructor(appDatabase: AppDatabase, application: Application) { private val chirps = ConcurrentHashMap() private val chirpSubjects = ConcurrentHashMap>() private val chirpsSubject: Subject> = BehaviorSubject.createDefault(emptySet()) + // TODO : used to fake page loading, to be removed when we will be able to request only wanted + // chirps. Maxime Teuber @Kaz-ookid - April 2024 + private var chirpsLoaded: AtomicInteger = AtomicInteger(0) + private var storageIsLoaded: Boolean = false + private var reachedEndOfChirps: Boolean = false // Reactions val reactionByChirpId = ConcurrentHashMap>() @@ -179,6 +192,7 @@ constructor(appDatabase: AppDatabase, application: Application) { init { loadStorage() + chirpsLoaded.set(CHIRPS_PAGE_SIZE) } fun add(chirp: Chirp) { @@ -188,6 +202,11 @@ constructor(appDatabase: AppDatabase, application: Application) { Timber.tag(TAG).w("A chirp with id %s already exist : %s", id, old) return } + if (storageIsLoaded) { + // TODO : used to fake page loading, to be removed when we will be able to request only + // wanted chirps. Maxime Teuber @Kaz-ookid - April 2024 + chirpsLoaded.incrementAndGet() + } // Update repository data chirps[id] = chirp @@ -199,6 +218,23 @@ constructor(appDatabase: AppDatabase, application: Application) { chirpsSubject.toSerialized().onNext(HashSet(chirps.keys)) } + // TODO : used to fake page loading, to be removed when we will be able to request only wanted + // chirps. Maxime Teuber @Kaz-ookid - April 2024 + // Either here or directly in DB, we should query to servers the CHIRPS_PAGE_SIZE next chirps, + // and not all of them. + fun queryMoreChirps() { + val previousSize = getChirpsSubject().blockingFirst().size + chirpsLoaded.addAndGet(CHIRPS_PAGE_SIZE) + chirpsSubject.onNext( + chirps.keys.sortedByDescending { chirps[it]?.timestamp }.take(chirpsLoaded.get()).toSet()) + val newSize = getChirpsSubject().blockingFirst().size + // if did not load CHIRPS_PAGE_SIZE chirps, then we reached the end of the chirps. + if (newSize - previousSize != CHIRPS_PAGE_SIZE) { + chirpsLoaded.set(newSize) + reachedEndOfChirps = true + } + } + fun addReaction(reaction: Reaction): Boolean { // Check if the associated chirp is present val chirp = chirps[reaction.chirpId] ?: return false @@ -279,7 +315,17 @@ constructor(appDatabase: AppDatabase, application: Application) { } fun getChirpsSubject(): Observable> { - return chirpsSubject + // TODO : used to fake page loading, to be removed when we will be able to request only wanted + // chirps. Maxime Teuber @Kaz-ookid - April 2024 + // would normally return chirpsSubject directly + return chirpsSubject.map { + chirps.keys.sortedByDescending { chirps[it]?.timestamp }.take(chirpsLoaded.get()).toSet() + } + } + + /** Check if the end of the chirps history has been reached */ + fun isEndOfChirps(): Boolean { + return reachedEndOfChirps } @Throws(UnknownChirpException::class) @@ -342,6 +388,7 @@ constructor(appDatabase: AppDatabase, application: Application) { chirp.id) })) }) + storageIsLoaded = true }, { err: Throwable -> Timber.tag(TAG).e(err, "No chirp found in the storage for lao %s", laoId) @@ -350,6 +397,7 @@ constructor(appDatabase: AppDatabase, application: Application) { } companion object { + private const val CHIRPS_PAGE_SIZE: Int = 10 private val TAG = SocialMediaRepository::class.java.simpleName } } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragment.kt index 2b1eccf91f..43449867c7 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragment.kt @@ -4,6 +4,8 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Button +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import com.github.dedis.popstellar.R @@ -39,6 +41,7 @@ class ChirpListFragment : Fragment() { super.onViewCreated(view, savedInstanceState) setupSendButton() setupListViewAdapter() + addLoadMoreButtonToListView() } override fun onResume() { @@ -62,6 +65,31 @@ class ChirpListFragment : Fragment() { listView.adapter = mChirpListAdapter } + private fun addLoadMoreButtonToListView() { + val footerView = + layoutInflater.inflate(R.layout.chirp_load_more_button, binding.chirpsList, false) + val buttonLoadMoreChirps = footerView.findViewById