Show loading animation while loading elements
[Sone.git] / src / main / kotlin / net / pterodactylus / sone / core / DefaultElementLoader.kt
1 package net.pterodactylus.sone.core
2
3 import com.google.common.cache.CacheBuilder
4 import freenet.keys.FreenetURI
5 import java.io.ByteArrayInputStream
6 import javax.imageio.ImageIO
7 import javax.inject.Inject
8
9 /**
10  * [ElementLoader] implementation that uses a simple Guava [com.google.common.cache.Cache].
11  */
12 class DefaultElementLoader @Inject constructor(private val freenetInterface: FreenetInterface) : ElementLoader {
13
14         private val loadingLinks = CacheBuilder.newBuilder().build<String, Boolean>()
15         private val imageCache = CacheBuilder.newBuilder().build<String, LinkedImage>()
16         private val callback = object : FreenetInterface.BackgroundFetchCallback {
17                 override fun loaded(uri: FreenetURI, mimeType: String, data: ByteArray) {
18                         if (!mimeType.startsWith("image/")) {
19                                 return
20                         }
21                         ByteArrayInputStream(data).use {
22                                 ImageIO.read(it)
23                         }?.let {
24                                 imageCache.get(uri.toString()) { LinkedImage(uri.toString()) }
25                         }
26                         removeLoadingLink(uri)
27                 }
28
29                 override fun failed(uri: FreenetURI) {
30                         removeLoadingLink(uri)
31                 }
32
33                 private fun removeLoadingLink(uri: FreenetURI) {
34                         synchronized(loadingLinks) {
35                                 loadingLinks.invalidate(uri.toString())
36                         }
37                 }
38         }
39
40         override fun loadElement(link: String): LinkedElement {
41                 synchronized(loadingLinks) {
42                         imageCache.getIfPresent(link)?.run {
43                                 return this
44                         }
45                         if (loadingLinks.getIfPresent(link) == null) {
46                                 loadingLinks.put(link, true)
47                                 freenetInterface.startFetch(FreenetURI(link), callback)
48                         }
49                 }
50                 return object : LinkedElement {
51                         override val link = link
52                         override val loading = true
53                 }
54         }
55
56 }