Skip to content

Commit 3ce44c2

Browse files
Okuro3499dogi
andcommitted
courses: smoother resources thumbnail previewing (fixes #11311) (#11313)
Co-authored-by: dogi <dogi@users.noreply.github.com>
1 parent cc9f99a commit 3ce44c2

11 files changed

Lines changed: 597 additions & 98 deletions

File tree

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ android {
1111
applicationId "org.ole.planet.myplanet"
1212
minSdk = 26
1313
targetSdk = 36
14-
versionCode = 4627
15-
versionName = "0.46.27"
14+
versionCode = 4628
15+
versionName = "0.46.28"
1616
ndkVersion = '26.3.11579264'
1717
vectorDrawables.useSupportLibrary = true
1818
}

app/src/main/java/org/ole/planet/myplanet/repository/ResourcesRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ interface ResourcesRepository {
1515
suspend fun getLibraryForSelectedUser(userId: String): List<RealmMyLibrary>
1616
suspend fun getMyLibrary(userId: String?): List<RealmMyLibrary>
1717
suspend fun getStepResources(stepId: String?, resourceOffline: Boolean): List<RealmMyLibrary>
18+
suspend fun getAllStepResources(stepId: String?): List<RealmMyLibrary>
1819
suspend fun getRecentResources(userId: String): Flow<List<RealmMyLibrary>>
1920
suspend fun getPendingDownloads(userId: String): Flow<List<RealmMyLibrary>>
2021
suspend fun getPrivateImagesCreatedAfter(timestamp: Long): List<RealmMyLibrary>
@@ -39,6 +40,7 @@ interface ResourcesRepository {
3940
mediums: Set<String>
4041
)
4142
suspend fun downloadResources(resources: List<RealmMyLibrary>): Boolean
43+
suspend fun downloadResourcesPriority(resources: List<RealmMyLibrary>): Boolean
4244
suspend fun getAllLibrariesToSync(): List<RealmMyLibrary>
4345
suspend fun addResourcesToUserLibrary(resourceIds: List<String>, userId: String)
4446
suspend fun addAllResourcesToUserLibrary(resources: List<RealmMyLibrary>, userId: String)

app/src/main/java/org/ole/planet/myplanet/repository/ResourcesRepositoryImpl.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ class ResourcesRepositoryImpl @Inject constructor(
8989
}
9090
}
9191

92+
override suspend fun getAllStepResources(stepId: String?): List<RealmMyLibrary> {
93+
if (stepId == null) return emptyList()
94+
95+
return queryList(RealmMyLibrary::class.java) {
96+
equalTo("stepId", stepId)
97+
}
98+
}
99+
92100
override suspend fun countLibrariesNeedingUpdate(userId: String?): Int {
93101
if (userId == null) return 0
94102

@@ -247,7 +255,18 @@ class ResourcesRepositoryImpl @Inject constructor(
247255
}
248256
true
249257
} catch (e: Exception) {
250-
e.printStackTrace()
258+
false
259+
}
260+
}
261+
262+
override suspend fun downloadResourcesPriority(resources: List<RealmMyLibrary>): Boolean {
263+
return try {
264+
val urls = resources.mapNotNull { it.resourceRemoteAddress }
265+
if (urls.isNotEmpty()) {
266+
DownloadUtils.openPriorityDownloadService(context, ArrayList(urls))
267+
}
268+
true
269+
} catch (e: Exception) {
251270
false
252271
}
253272
}

app/src/main/java/org/ole/planet/myplanet/services/DownloadService.kt

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,8 @@ class DownloadService : Service() {
4848
private var notificationManager: NotificationManager? = null
4949
private var totalFileSize = 0
5050
private lateinit var preferences: SharedPreferences
51-
private lateinit var urls: Array<String>
52-
private var currentIndex = 0
51+
private var currentDownloadUrl: String = ""
5352
private var fromSync = false
54-
5553
private var totalDownloadsCount = 0
5654
private var completedDownloadsCount = 0
5755
private var lastNotificationUpdateTime = 0L
@@ -85,37 +83,64 @@ class DownloadService : Service() {
8583

8684
private suspend fun processDownloadQueue() {
8785
while (true) {
88-
val pendingUrls = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet())?.toMutableSet() ?: mutableSetOf()
89-
90-
val newUrls = pendingUrls.filter { it !in processedUrls }
86+
val nextUrl = getNextPriorityUrl() ?: getNextPendingUrl()
9187

92-
if (newUrls.isEmpty()) {
88+
if (nextUrl == null) {
9389
if (sessionCompletedCount > 0) {
9490
showCompletionNotification(false)
9591
}
9692

97-
preferences.edit { remove(PENDING_DOWNLOADS_KEY) }
93+
preferences.edit {
94+
remove(PENDING_DOWNLOADS_KEY)
95+
remove(PRIORITY_DOWNLOADS_KEY)
96+
}
9897
stopSelf()
9998
return
10099
}
101100

102-
urls = newUrls.toTypedArray()
103-
totalDownloadsCount = urls.size
104-
sessionTotalCount += urls.size
105-
completedDownloadsCount = 0
106-
currentIndex = 0
101+
processedUrls.add(nextUrl.url)
102+
sessionTotalCount++
103+
totalDownloadsCount = getRemainingCount() + 1
107104

108105
updateNotificationForBatchDownload()
106+
initDownload(nextUrl.url, fromSync)
109107

110-
urls.forEachIndexed { index, url ->
111-
currentIndex = index
112-
processedUrls.add(url)
113-
initDownload(url, fromSync)
114-
}
108+
completedDownloadsCount++
109+
sessionCompletedCount++
110+
111+
cleanupProcessedUrls()
112+
}
113+
}
114+
115+
private data class QueuedUrl(val url: String, val isPriority: Boolean)
116+
117+
private fun getNextPriorityUrl(): QueuedUrl? {
118+
val priorityUrls = preferences.getStringSet(PRIORITY_DOWNLOADS_KEY, emptySet()) ?: emptySet()
119+
val next = priorityUrls.firstOrNull { it !in processedUrls && it.isNotBlank() }
120+
return next?.let { QueuedUrl(it, isPriority = true) }
121+
}
122+
123+
private fun getNextPendingUrl(): QueuedUrl? {
124+
val pendingUrls = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet()) ?: emptySet()
125+
val next = pendingUrls.firstOrNull { it !in processedUrls && it.isNotBlank() }
126+
return next?.let { QueuedUrl(it, isPriority = false) }
127+
}
128+
129+
private fun getRemainingCount(): Int {
130+
val priorityUrls = preferences.getStringSet(PRIORITY_DOWNLOADS_KEY, emptySet()) ?: emptySet()
131+
val pendingUrls = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet()) ?: emptySet()
132+
val allUrls = priorityUrls + pendingUrls
133+
return allUrls.count { it !in processedUrls }
134+
}
115135

116-
val remainingUrls = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet())?.toMutableSet() ?: mutableSetOf()
117-
remainingUrls.removeAll(processedUrls)
118-
preferences.edit { putStringSet(PENDING_DOWNLOADS_KEY, remainingUrls) }
136+
private fun cleanupProcessedUrls() {
137+
val remainingPriority = preferences.getStringSet(PRIORITY_DOWNLOADS_KEY, emptySet())?.toMutableSet() ?: mutableSetOf()
138+
remainingPriority.removeAll(processedUrls)
139+
val remainingPending = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet())?.toMutableSet() ?: mutableSetOf()
140+
remainingPending.removeAll(processedUrls)
141+
preferences.edit {
142+
putStringSet(PRIORITY_DOWNLOADS_KEY, remainingPriority)
143+
putStringSet(PENDING_DOWNLOADS_KEY, remainingPending)
119144
}
120145
}
121146

@@ -135,12 +160,13 @@ class DownloadService : Service() {
135160
}
136161

137162
private suspend fun initDownload(url: String, fromSync: Boolean) {
163+
currentDownloadUrl = url
138164
try {
139165
if (url.isBlank()) {
140166
downloadFailed("Invalid URL - empty or blank", fromSync)
141167
return
142168
}
143-
169+
144170
val retrofitInterface = ApiClient.client.create(ApiInterface::class.java)
145171
if (retrofitInterface == null) {
146172
downloadFailed("Network client not available", fromSync)
@@ -223,16 +249,10 @@ class DownloadService : Service() {
223249
}
224250

225251
private fun downloadFailed(message: String, fromSync: Boolean) {
226-
completedDownloadsCount++
227-
sessionCompletedCount++
228-
229-
val pendingUrls = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet()) ?: emptySet()
230-
val remainingInQueue = pendingUrls.count { it !in processedUrls }
231-
val totalRemaining = (totalDownloadsCount - completedDownloadsCount) + remainingInQueue
232-
val displayTotal = sessionCompletedCount + totalRemaining
233-
252+
val remaining = getRemainingCount()
234253
notificationBuilder?.apply {
235-
setContentText("Error: $message ($sessionCompletedCount/$displayTotal)")
254+
setContentText("Error: $message")
255+
setSubText("$sessionCompletedCount completed, $remaining remaining")
236256
notificationManager?.notify(ONGOING_NOTIFICATION_ID, build())
237257
}
238258

@@ -297,7 +317,6 @@ class DownloadService : Service() {
297317
}
298318
}
299319
}
300-
301320
onDownloadComplete(url)
302321
}
303322

@@ -316,16 +335,16 @@ class DownloadService : Service() {
316335
}
317336

318337
private fun sendNotification(download: Download) {
319-
val url = urls.getOrNull(currentIndex) ?: run {
320-
return
321-
}
338+
val url = currentDownloadUrl
339+
if (url.isBlank()) return
322340

323341
download.fileName = "Downloading: ${getFileNameFromUrl(url)}"
324342
sendIntent(download, fromSync)
325343

326344
if (NotificationManagerCompat.from(this).areNotificationsEnabled()) {
327345
notificationBuilder?.apply {
328346
val fileName = getFileNameFromUrl(url)
347+
val remaining = getRemainingCount()
329348
val progressText = if (currentFileProgress in 0..100) {
330349
"$fileName ($currentFileProgress%)"
331350
} else {
@@ -334,10 +353,10 @@ class DownloadService : Service() {
334353

335354
if (currentFileProgress in 0..100) {
336355
setProgress(100, currentFileProgress, false)
337-
setSubText("${currentIndex + 1}/$totalDownloadsCount files")
356+
setSubText("$sessionCompletedCount completed, $remaining remaining")
338357
} else {
339358
setProgress(100, 0, true)
340-
setSubText("${currentIndex + 1}/$totalDownloadsCount files")
359+
setSubText("$sessionCompletedCount completed, $remaining remaining")
341360
}
342361
setContentText(progressText)
343362
notificationManager?.notify(ONGOING_NOTIFICATION_ID, build())
@@ -360,26 +379,21 @@ class DownloadService : Service() {
360379
if ((outputFile?.length() ?: 0) > 0) {
361380
DownloadUtils.updateResourceOfflineStatus(url)
362381
}
363-
completedDownloadsCount++
364-
sessionCompletedCount++
365382

366-
val pendingUrls = preferences.getStringSet(PENDING_DOWNLOADS_KEY, emptySet()) ?: emptySet()
367-
val remainingInQueue = pendingUrls.count { it !in processedUrls }
368-
val totalRemaining = (totalDownloadsCount - completedDownloadsCount) + remainingInQueue
383+
val remaining = getRemainingCount()
369384

370385
val download = Download().apply {
371386
fileName = getFileNameFromUrl(url)
372387
fileUrl = url
373388
progress = 100
374-
completeAll = (totalRemaining == 0)
389+
completeAll = (remaining == 0)
375390
}
376391

377392
sendIntent(download, fromSync)
378393
notificationBuilder?.apply {
379-
val displayTotal = sessionCompletedCount + totalRemaining
380-
setProgress(displayTotal, sessionCompletedCount, false)
381-
setContentText("Downloaded $sessionCompletedCount/$displayTotal files")
382-
setSubText(null)
394+
setProgress(sessionCompletedCount + remaining, sessionCompletedCount, false)
395+
setContentText("Downloaded ${getFileNameFromUrl(url)}")
396+
setSubText("$sessionCompletedCount completed, $remaining remaining")
383397
notificationManager?.notify(ONGOING_NOTIFICATION_ID, build())
384398
}
385399
}
@@ -414,6 +428,7 @@ class DownloadService : Service() {
414428
const val COMPLETION_NOTIFICATION_ID = 2
415429
private const val NOTIFICATION_UPDATE_INTERVAL_MS = 500L
416430
const val PENDING_DOWNLOADS_KEY = "pending_downloads_queue"
431+
const val PRIORITY_DOWNLOADS_KEY = "priority_downloads_queue"
417432

418433
fun startService(context: Context, urlsKey: String, fromSync: Boolean) {
419434
val intent = Intent(context, DownloadService::class.java).apply {

0 commit comments

Comments
 (0)