Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.livingwithhippos.unchained.data.repository

import android.os.SystemClock
import android.util.LruCache
import com.github.livingwithhippos.unchained.data.local.ProtoStore
import com.github.livingwithhippos.unchained.data.model.DownloadItem
import com.github.livingwithhippos.unchained.data.model.UnchainedNetworkException
Expand All @@ -16,12 +18,28 @@ class UnrestrictRepository
constructor(protoStore: ProtoStore, private val unrestrictApiHelper: UnrestrictApiHelper) :
BaseRepository(protoStore) {

private val unrestrictedLinkCache =
LruCache<UnrestrictedLinkCacheKey, CachedUnrestrictedLink>(
UNRESTRICTED_LINK_CACHE_MAX_ENTRIES
)

suspend fun getEitherUnrestrictedLink(
link: String,
password: String? = null,
remote: Int? = null,
): EitherResult<UnchainedNetworkException, DownloadItem> {
val token = getToken()
val cacheKey =
UnrestrictedLinkCacheKey(
token = token,
link = link,
password = password,
remote = remote,
)

getCachedUnrestrictedLink(cacheKey)?.let {
return EitherResult.Success(it)
}

val linkResponse =
eitherApiResult(
Expand All @@ -36,9 +54,17 @@ constructor(protoStore: ProtoStore, private val unrestrictApiHelper: UnrestrictA
errorMessage = "Error Fetching Unrestricted Link Info",
)

if (linkResponse is EitherResult.Success) {
cacheUnrestrictedLink(cacheKey, linkResponse.success)
}

return linkResponse
}

fun clearUnrestrictedLinkCache() {
synchronized(unrestrictedLinkCache) { unrestrictedLinkCache.evictAll() }
}

suspend fun getUnrestrictedLinkList(
linksList: List<String>,
password: String? = null,
Expand Down Expand Up @@ -110,4 +136,46 @@ constructor(protoStore: ProtoStore, private val unrestrictApiHelper: UnrestrictA

return containerResponse
}

private fun cacheUnrestrictedLink(key: UnrestrictedLinkCacheKey, item: DownloadItem) {
synchronized(unrestrictedLinkCache) {
unrestrictedLinkCache.put(
key,
CachedUnrestrictedLink(
item = item,
createdAtElapsedRealtime = SystemClock.elapsedRealtime(),
),
)
}
}

private fun getCachedUnrestrictedLink(key: UnrestrictedLinkCacheKey): DownloadItem? =
synchronized(unrestrictedLinkCache) {
val cachedLink = unrestrictedLinkCache.get(key) ?: return@synchronized null
val cacheAge = SystemClock.elapsedRealtime() - cachedLink.createdAtElapsedRealtime

if (cacheAge <= UNRESTRICTED_LINK_CACHE_TTL_MS) {
cachedLink.item
} else {
unrestrictedLinkCache.remove(key)
null
}
}

private data class UnrestrictedLinkCacheKey(
val token: String,
val link: String,
val password: String?,
val remote: Int?,
)

private data class CachedUnrestrictedLink(
val item: DownloadItem,
val createdAtElapsedRealtime: Long,
)

companion object {
private const val UNRESTRICTED_LINK_CACHE_MAX_ENTRIES = 5000
private const val UNRESTRICTED_LINK_CACHE_TTL_MS = 2 * 60 * 60 * 1000L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,7 @@ class FolderListFragment : UnchainedFragment(), DownloadListListener {

// observe the list loading status
viewModel.folderLiveData.observe(viewLifecycleOwner) {
it.getContentIfNotHandled()?.let { _ ->
updateList(adapter)
// scroll only if the results are still coming in
if (viewModel.getScrollingAllowed()) {
lifecycleScope.launch {
binding.rvFolderList.delayedScrolling(requireContext(), delay = 500)
}
}
}
it.getContentIfNotHandled()?.let { _ -> updateList(adapter) }
}

// observe errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ constructor(
}
is EitherResult.Success -> {
hitList.add(file.success)
folderLiveData.postEvent(hitList)
folderLiveData.postEvent(hitList.toList())
setRetrievedLinks(hitList.size)
progressLiveData.postValue((index + 1) * 100 / links.size)
}
Expand Down