diff --git a/app/src/main/kotlin/com/github/gotify/CoilHandler.kt b/app/src/main/kotlin/com/github/gotify/CoilInstance.kt similarity index 57% rename from app/src/main/kotlin/com/github/gotify/CoilHandler.kt rename to app/src/main/kotlin/com/github/gotify/CoilInstance.kt index 94781115..611e6fbd 100644 --- a/app/src/main/kotlin/com/github/gotify/CoilHandler.kt +++ b/app/src/main/kotlin/com/github/gotify/CoilInstance.kt @@ -16,40 +16,26 @@ import java.io.IOException import okhttp3.OkHttpClient import org.tinylog.kotlin.Logger -internal class CoilHandler(private val context: Context, private val settings: Settings) { - private val imageLoader = makeImageLoader() - - private fun makeImageLoader(): ImageLoader { - val builder = OkHttpClient.Builder() - CertUtils.applySslSettings(builder, settings.sslSettings()) - return ImageLoader.Builder(context) - .okHttpClient(builder.build()) - .diskCache { - DiskCache.Builder() - .directory(context.cacheDir.resolve("coil-cache")) - .build() - } - .components { - add(SvgDecoder.Factory()) - } - .build() - } +object CoilInstance { + private var holder: Pair? = null @Throws(IOException::class) - fun getImageFromUrl(url: String?): Bitmap { + fun getImageFromUrl(context: Context, url: String?): Bitmap { val request = ImageRequest.Builder(context) .data(url) .build() - return (imageLoader.executeBlocking(request).drawable as BitmapDrawable).bitmap + return (get(context).executeBlocking(request).drawable as BitmapDrawable).bitmap } - fun getIcon(app: Application?): Bitmap { + fun getIcon(context: Context, app: Application?): Bitmap { if (app == null) { return BitmapFactory.decodeResource(context.resources, R.drawable.gotify) } + val baseUrl = Settings(context).url try { return getImageFromUrl( - Utils.resolveAbsoluteUrl("${settings.url}/", app.image) + context, + Utils.resolveAbsoluteUrl("$baseUrl/", app.image) ) } catch (e: IOException) { Logger.error(e, "Could not load image for notification") @@ -57,15 +43,45 @@ internal class CoilHandler(private val context: Context, private val settings: S return BitmapFactory.decodeResource(context.resources, R.drawable.gotify) } - fun get() = imageLoader - @OptIn(ExperimentalCoilApi::class) - fun evict() { + fun evict(context: Context) { try { - imageLoader.diskCache?.clear() - imageLoader.memoryCache?.clear() + get(context).apply { + diskCache?.clear() + memoryCache?.clear() + } } catch (e: IOException) { Logger.error(e, "Problem evicting Coil cache") } } + + @Synchronized + fun get(context: Context): ImageLoader { + val newSettings = Settings(context).sslSettings() + val copy = holder + if (copy != null && copy.first == newSettings) { + return copy.second + } + return makeImageLoader(context, newSettings).also { holder = it }.second + } + + private fun makeImageLoader( + context: Context, + sslSettings: SSLSettings + ): Pair { + val builder = OkHttpClient.Builder() + CertUtils.applySslSettings(builder, sslSettings) + val loader = ImageLoader.Builder(context) + .okHttpClient(builder.build()) + .diskCache { + DiskCache.Builder() + .directory(context.cacheDir.resolve("coil-cache")) + .build() + } + .components { + add(SvgDecoder.Factory()) + } + .build() + return sslSettings to loader + } } diff --git a/app/src/main/kotlin/com/github/gotify/SSLSettings.kt b/app/src/main/kotlin/com/github/gotify/SSLSettings.kt index cc88a607..eb900b66 100644 --- a/app/src/main/kotlin/com/github/gotify/SSLSettings.kt +++ b/app/src/main/kotlin/com/github/gotify/SSLSettings.kt @@ -1,6 +1,6 @@ package com.github.gotify -internal class SSLSettings( +internal data class SSLSettings( val validateSSL: Boolean, val caCertPath: String?, val clientCertPath: String?, diff --git a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt index 514acf22..421adb36 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt @@ -31,6 +31,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import coil.request.ImageRequest import com.github.gotify.BuildConfig +import com.github.gotify.CoilInstance import com.github.gotify.MissedMessageUtil import com.github.gotify.R import com.github.gotify.Utils @@ -102,7 +103,7 @@ internal class MessagesActivity : listMessageAdapter = ListMessageAdapter( this, viewModel.settings, - viewModel.coilHandler.get() + CoilInstance.get(this) ) { message -> scheduleDeletion(message) } @@ -169,13 +170,13 @@ internal class MessagesActivity : } private fun refreshAll() { - viewModel.coilHandler.evict() + CoilInstance.evict(this) startActivity(Intent(this, InitializationActivity::class.java)) finish() } private fun onRefresh() { - viewModel.coilHandler.evict() + CoilInstance.evict(this) viewModel.messages.clear() launchCoroutine { loadMore(viewModel.appId).forEachIndexed { index, message -> @@ -211,9 +212,7 @@ internal class MessagesActivity : .size(100, 100) .target(t) .build() - viewModel.coilHandler - .get() - .enqueue(request) + CoilInstance.get(this).enqueue(request) } selectAppInMenu(selectedItem) } diff --git a/app/src/main/kotlin/com/github/gotify/messages/MessagesModel.kt b/app/src/main/kotlin/com/github/gotify/messages/MessagesModel.kt index a7383069..e4ae8e4c 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/MessagesModel.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/MessagesModel.kt @@ -3,7 +3,6 @@ package com.github.gotify.messages import android.app.Activity import androidx.lifecycle.ViewModel import coil.target.Target -import com.github.gotify.CoilHandler import com.github.gotify.Settings import com.github.gotify.api.ClientFactory import com.github.gotify.client.api.MessageApi @@ -13,7 +12,6 @@ import com.github.gotify.messages.provider.MessageState internal class MessagesModel(parentView: Activity) : ViewModel() { val settings = Settings(parentView) - val coilHandler = CoilHandler(parentView, settings) val client = ClientFactory.clientToken(settings) val appsHolder = ApplicationHolder(parentView, client) val messages = MessageFacade(client.createService(MessageApi::class.java), appsHolder) diff --git a/app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt b/app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt index 402aa808..7ad0078c 100644 --- a/app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt +++ b/app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt @@ -17,7 +17,7 @@ import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import com.github.gotify.BuildConfig -import com.github.gotify.CoilHandler +import com.github.gotify.CoilInstance import com.github.gotify.MarkwonFactory import com.github.gotify.MissedMessageUtil import com.github.gotify.NotificationSupport @@ -62,7 +62,6 @@ internal class WebSocketService : Service() { private val lastReceivedMessage = AtomicLong(NOT_LOADED) private lateinit var missingMessageUtil: MissedMessageUtil - private lateinit var coilHandler: CoilHandler private lateinit var markwon: Markwon override fun onCreate() { @@ -71,8 +70,7 @@ internal class WebSocketService : Service() { val client = ClientFactory.clientToken(settings) missingMessageUtil = MissedMessageUtil(client.createService(MessageApi::class.java)) Logger.info("Create ${javaClass.simpleName}") - coilHandler = CoilHandler(this, settings) - markwon = MarkwonFactory.createForNotification(this, coilHandler.get()) + markwon = MarkwonFactory.createForNotification(this, CoilInstance.get(this)) } override fun onDestroy() { @@ -377,7 +375,7 @@ internal class WebSocketService : Service() { .setDefaults(Notification.DEFAULT_ALL) .setWhen(System.currentTimeMillis()) .setSmallIcon(R.drawable.ic_gotify) - .setLargeIcon(coilHandler.getIcon(appIdToApp[appId])) + .setLargeIcon(CoilInstance.getIcon(this, appIdToApp[appId])) .setTicker("${getString(R.string.app_name)} - $title") .setGroup(NotificationSupport.Group.MESSAGES) .setContentTitle(title) @@ -406,7 +404,7 @@ internal class WebSocketService : Service() { try { b.setStyle( NotificationCompat.BigPictureStyle() - .bigPicture(coilHandler.getImageFromUrl(notificationImageUrl)) + .bigPicture(CoilInstance.getImageFromUrl(this, notificationImageUrl)) ) } catch (e: Exception) { Logger.error(e, "Error loading bigImageUrl")