mirror of
https://github.com/GrakovNe/lissen-android.git
synced 2026-07-31 10:28:12 -04:00
Feature/99 fix progress sync (#115)
This commit is contained in:
@@ -29,8 +29,8 @@ android {
|
||||
applicationId = "org.grakovne.lissen"
|
||||
minSdk = 28
|
||||
targetSdk = 35
|
||||
versionCode = 67
|
||||
versionName = "1.2.6"
|
||||
versionCode = 68
|
||||
versionName = "1.2.7"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
||||
@@ -56,14 +56,16 @@ abstract class AudiobookshelfChannel(
|
||||
.map { libraryResponseConverter.apply(it) }
|
||||
|
||||
override suspend fun fetchRecentListenedBooks(libraryId: String): ApiResult<List<RecentBook>> {
|
||||
val progress: Map<String, Double> = dataRepository
|
||||
val progress: Map<String, Pair<Long, Double>> = dataRepository
|
||||
.fetchUserInfoResponse()
|
||||
.fold(
|
||||
onSuccess = {
|
||||
it
|
||||
.user
|
||||
.mediaProgress
|
||||
?.associate { item -> item.libraryItemId to item.progress }
|
||||
?.groupBy { item -> item.libraryItemId }
|
||||
?.map { (item, value) -> item to value.maxBy { progress -> progress.lastUpdate } }
|
||||
?.associate { (item, progress) -> item to (progress.lastUpdate to progress.progress) }
|
||||
?: emptyMap()
|
||||
},
|
||||
onFailure = { emptyMap() },
|
||||
|
||||
@@ -10,7 +10,7 @@ class RecentListeningResponseConverter @Inject constructor() {
|
||||
|
||||
fun apply(
|
||||
response: List<PersonalizedFeedResponse>,
|
||||
progress: Map<String, Double>,
|
||||
progress: Map<String, Pair<Long, Double>>,
|
||||
): List<RecentBook> = response
|
||||
.find { it.labelStringKey == LABEL_CONTINUE_LISTENING }
|
||||
?.entities
|
||||
@@ -20,7 +20,8 @@ class RecentListeningResponseConverter @Inject constructor() {
|
||||
id = it.id,
|
||||
title = it.media.metadata.title,
|
||||
author = it.media.metadata.authorName,
|
||||
listenedPercentage = progress[it.id]?.let { it * 100 }?.toInt(),
|
||||
listenedPercentage = progress[it.id]?.second?.let { it * 100 }?.toInt(),
|
||||
listenedLastUpdate = progress[it.id]?.first ,
|
||||
)
|
||||
} ?: emptyList()
|
||||
|
||||
|
||||
@@ -151,7 +151,9 @@ class LissenMediaProvider @Inject constructor(
|
||||
|
||||
return when (sharedPreferences.isForceCache()) {
|
||||
true -> localCacheRepository.fetchRecentListenedBooks()
|
||||
false -> providePreferredChannel().fetchRecentListenedBooks(libraryId)
|
||||
false -> providePreferredChannel()
|
||||
.fetchRecentListenedBooks(libraryId)
|
||||
.map { items -> syncFromLocalProgress(items) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +184,37 @@ class LissenMediaProvider @Inject constructor(
|
||||
return provideAuthService().authorize(host, username, password)
|
||||
}
|
||||
|
||||
private suspend fun syncFromLocalProgress(
|
||||
detailedItems: List<RecentBook>,
|
||||
): List<RecentBook> {
|
||||
val localRecentlyBooks = localCacheRepository
|
||||
.fetchRecentListenedBooks()
|
||||
.fold(
|
||||
onSuccess = { it },
|
||||
onFailure = { return@fold detailedItems },
|
||||
)
|
||||
|
||||
val syncedRecentlyBooks = detailedItems
|
||||
.mapNotNull { item -> localRecentlyBooks.find { it.id == item.id }?.let { item to it } }
|
||||
.map { (remote, local) ->
|
||||
val localTimestamp = local.listenedLastUpdate ?: return@map remote
|
||||
val remoteTimestamp = remote.listenedLastUpdate ?: return@map remote
|
||||
|
||||
when (remoteTimestamp > localTimestamp) {
|
||||
true -> remote
|
||||
false -> local
|
||||
}
|
||||
}
|
||||
|
||||
return detailedItems
|
||||
.map { item ->
|
||||
syncedRecentlyBooks
|
||||
.find { item.id == it.id }
|
||||
?.let { local -> item.copy(listenedPercentage = local.listenedPercentage) }
|
||||
?: item
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun syncFromLocalProgress(detailedItem: DetailedItem): DetailedItem {
|
||||
val cachedBook = localCacheRepository.fetchBook(detailedItem.id) ?: return detailedItem
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class CachedBookRepository @Inject constructor(
|
||||
val progress = recentBooks
|
||||
.map { it.id }
|
||||
.mapNotNull { bookDao.fetchMediaProgress(it) }
|
||||
.associate { it.bookId to it.currentTime }
|
||||
.associate { it.bookId to (it.lastUpdate to it.currentTime) }
|
||||
|
||||
return recentBooks
|
||||
.map { cachedBookEntityRecentConverter.apply(it, progress[it.id]) }
|
||||
|
||||
@@ -8,11 +8,13 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class CachedBookEntityRecentConverter @Inject constructor() {
|
||||
|
||||
fun apply(entity: BookEntity, currentTime: Double?): RecentBook = RecentBook(
|
||||
fun apply(entity: BookEntity, currentTime: Pair<Long, Double>?): RecentBook = RecentBook(
|
||||
id = entity.id,
|
||||
title = entity.title,
|
||||
author = entity.author,
|
||||
listenedLastUpdate = currentTime?.first ?: 0,
|
||||
listenedPercentage = currentTime
|
||||
?.second
|
||||
?.let { it / entity.duration }
|
||||
?.let { it * 100 }
|
||||
?.toInt(),
|
||||
|
||||
@@ -5,4 +5,5 @@ data class RecentBook(
|
||||
val title: String,
|
||||
val author: String?,
|
||||
val listenedPercentage: Int?,
|
||||
val listenedLastUpdate: Long?,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user