diff --git a/app/build.gradle b/app/build.gradle index 5eb89010..75f2ccc4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,7 @@ if (project.hasProperty('sign')) { } dependencies { + def markwon_version = "4.6.2" implementation project(':client') implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.core:core-splashscreen:1.0.1' @@ -76,12 +77,12 @@ dependencies { implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'com.github.cyb3rko:QuickPermissions-Kotlin:1.1.3' - implementation 'com.squareup.picasso:picasso:2.71828' - implementation 'io.noties.markwon:core:4.6.2' - implementation 'io.noties.markwon:image-picasso:4.6.2' - implementation 'io.noties.markwon:image:4.6.2' - implementation 'io.noties.markwon:ext-tables:4.6.2' - implementation 'io.noties.markwon:ext-strikethrough:4.6.2' + implementation 'io.coil-kt:coil:2.6.0' + implementation "io.noties.markwon:core:$markwon_version" + implementation "io.noties.markwon:image-coil:$markwon_version" + implementation "io.noties.markwon:image:$markwon_version" + implementation "io.noties.markwon:ext-tables:$markwon_version" + implementation "io.noties.markwon:ext-strikethrough:$markwon_version" implementation 'org.tinylog:tinylog-api-kotlin:2.6.2' implementation 'org.tinylog:tinylog-impl:2.6.2' diff --git a/app/src/main/kotlin/com/github/gotify/CoilHandler.kt b/app/src/main/kotlin/com/github/gotify/CoilHandler.kt new file mode 100644 index 00000000..26ff360d --- /dev/null +++ b/app/src/main/kotlin/com/github/gotify/CoilHandler.kt @@ -0,0 +1,67 @@ +package com.github.gotify + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.drawable.BitmapDrawable +import coil.ImageLoader +import coil.annotation.ExperimentalCoilApi +import coil.disk.DiskCache +import coil.executeBlocking +import coil.request.ImageRequest +import com.github.gotify.api.CertUtils +import com.github.gotify.client.model.Application +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() + } + .build() + } + + @Throws(IOException::class) + fun getImageFromUrl(url: String?): Bitmap { + val request = ImageRequest.Builder(context) + .data(url) + .build() + return (imageLoader.executeBlocking(request).drawable as BitmapDrawable).bitmap + } + + fun getIcon(app: Application?): Bitmap { + if (app == null) { + return BitmapFactory.decodeResource(context.resources, R.drawable.gotify) + } + try { + return getImageFromUrl( + Utils.resolveAbsoluteUrl("${settings.url}/", app.image) + ) + } catch (e: IOException) { + Logger.error(e, "Could not load image for notification") + } + return BitmapFactory.decodeResource(context.resources, R.drawable.gotify) + } + + fun get() = imageLoader + + @OptIn(ExperimentalCoilApi::class) + fun evict() { + try { + imageLoader.diskCache?.clear() + imageLoader.memoryCache?.clear() + } catch (e: IOException) { + Logger.error(e, "Problem evicting Coil cache") + } + } +} diff --git a/app/src/main/kotlin/com/github/gotify/MarkwonFactory.kt b/app/src/main/kotlin/com/github/gotify/MarkwonFactory.kt index 9bee6031..0aebc294 100644 --- a/app/src/main/kotlin/com/github/gotify/MarkwonFactory.kt +++ b/app/src/main/kotlin/com/github/gotify/MarkwonFactory.kt @@ -10,7 +10,7 @@ import android.text.style.RelativeSizeSpan import android.text.style.StyleSpan import android.text.style.TypefaceSpan import androidx.core.content.ContextCompat -import com.squareup.picasso.Picasso +import coil.ImageLoader import io.noties.markwon.AbstractMarkwonPlugin import io.noties.markwon.Markwon import io.noties.markwon.MarkwonSpansFactory @@ -22,7 +22,7 @@ import io.noties.markwon.core.MarkwonTheme import io.noties.markwon.ext.strikethrough.StrikethroughPlugin import io.noties.markwon.ext.tables.TableAwareMovementMethod import io.noties.markwon.ext.tables.TablePlugin -import io.noties.markwon.image.picasso.PicassoImagesPlugin +import io.noties.markwon.image.coil.CoilImagesPlugin import io.noties.markwon.movement.MovementMethodPlugin import org.commonmark.ext.gfm.tables.TableCell import org.commonmark.ext.gfm.tables.TablesExtension @@ -36,11 +36,11 @@ import org.commonmark.node.StrongEmphasis import org.commonmark.parser.Parser internal object MarkwonFactory { - fun createForMessage(context: Context, picasso: Picasso): Markwon { + fun createForMessage(context: Context, imageLoader: ImageLoader): Markwon { return Markwon.builder(context) .usePlugin(CorePlugin.create()) .usePlugin(MovementMethodPlugin.create(TableAwareMovementMethod.create())) - .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(CoilImagesPlugin.create(context, imageLoader)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(TablePlugin.create(context)) .usePlugin(object : AbstractMarkwonPlugin() { @@ -52,13 +52,13 @@ internal object MarkwonFactory { .build() } - fun createForNotification(context: Context, picasso: Picasso): Markwon { + fun createForNotification(context: Context, imageLoader: ImageLoader): Markwon { val headingSizes = floatArrayOf(2f, 1.5f, 1.17f, 1f, .83f, .67f) val bulletGapWidth = (8 * context.resources.displayMetrics.density + 0.5f).toInt() return Markwon.builder(context) .usePlugin(CorePlugin.create()) - .usePlugin(PicassoImagesPlugin.create(picasso)) + .usePlugin(CoilImagesPlugin.create(context, imageLoader)) .usePlugin(StrikethroughPlugin.create()) .usePlugin(object : AbstractMarkwonPlugin() { override fun configureSpansFactory(builder: MarkwonSpansFactory.Builder) { diff --git a/app/src/main/kotlin/com/github/gotify/Utils.kt b/app/src/main/kotlin/com/github/gotify/Utils.kt index 196d0481..277b4be1 100644 --- a/app/src/main/kotlin/com/github/gotify/Utils.kt +++ b/app/src/main/kotlin/com/github/gotify/Utils.kt @@ -3,19 +3,15 @@ package com.github.gotify import android.app.Activity import android.app.ActivityManager import android.content.Context -import android.content.res.Resources -import android.graphics.Bitmap -import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.text.format.DateUtils import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope +import coil.target.Target import com.github.gotify.client.JSON import com.google.android.material.snackbar.Snackbar import com.google.gson.Gson -import com.squareup.picasso.Picasso.LoadedFrom -import com.squareup.picasso.Target import java.io.BufferedReader import java.io.IOException import java.io.InputStream @@ -72,17 +68,15 @@ internal object Utils { } } - fun toDrawable(resources: Resources?, drawableReceiver: DrawableReceiver): Target { + fun toDrawable(drawableReceiver: DrawableReceiver): Target { return object : Target { - override fun onBitmapLoaded(bitmap: Bitmap, from: LoadedFrom) { - drawableReceiver.loaded(BitmapDrawable(resources, bitmap)) + override fun onSuccess(result: Drawable) { + drawableReceiver.loaded(result) } - override fun onBitmapFailed(e: Exception, errorDrawable: Drawable) { - Logger.error(e, "Bitmap failed") + override fun onError(error: Drawable?) { + Logger.error("Bitmap failed") } - - override fun onPrepareLoad(placeHolderDrawable: Drawable) {} } } diff --git a/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt b/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt index 1f2d31ef..79b1b08e 100644 --- a/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt +++ b/app/src/main/kotlin/com/github/gotify/login/LoginActivity.kt @@ -32,7 +32,7 @@ import com.github.gotify.log.UncaughtExceptionHandler import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.textfield.TextInputEditText import java.security.cert.X509Certificate -import okhttp3.HttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.tinylog.kotlin.Logger internal class LoginActivity : AppCompatActivity() { @@ -101,13 +101,13 @@ internal class LoginActivity : AppCompatActivity() { private fun doCheckUrl() { val url = binding.gotifyUrlEditext.text.toString().trim().trimEnd('/') - val parsedUrl = HttpUrl.parse(url) + val parsedUrl = url.toHttpUrlOrNull() if (parsedUrl == null) { Utils.showSnackBar(this, "Invalid URL (include http:// or https://)") return } - if ("http" == parsedUrl.scheme()) { + if ("http" == parsedUrl.scheme) { showHttpWarning() } diff --git a/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt b/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt index a11f0500..d87ef7a7 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/ListMessageAdapter.kt @@ -18,6 +18,8 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding +import coil.ImageLoader +import coil.load import com.github.gotify.MarkwonFactory import com.github.gotify.R import com.github.gotify.Settings @@ -26,7 +28,6 @@ import com.github.gotify.client.model.Message import com.github.gotify.databinding.MessageItemBinding import com.github.gotify.databinding.MessageItemCompactBinding import com.github.gotify.messages.provider.MessageWithImage -import com.squareup.picasso.Picasso import io.noties.markwon.Markwon import java.text.DateFormat import java.util.Date @@ -35,11 +36,11 @@ import org.threeten.bp.OffsetDateTime internal class ListMessageAdapter( private val context: Context, private val settings: Settings, - private val picasso: Picasso, + private val imageLoader: ImageLoader, private val delete: Delete ) : ListAdapter(DiffCallback) { private val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) - private val markwon: Markwon = MarkwonFactory.createForMessage(context, picasso) + private val markwon: Markwon = MarkwonFactory.createForMessage(context, imageLoader) private val timeFormatRelative = context.resources.getString(R.string.time_format_value_relative) @@ -81,10 +82,11 @@ internal class ListMessageAdapter( } holder.title.text = message.message.title if (message.image != null) { - picasso.load(Utils.resolveAbsoluteUrl("${settings.url}/", message.image)) - .error(R.drawable.ic_alarm) - .placeholder(R.drawable.ic_placeholder) - .into(holder.image) + val url = Utils.resolveAbsoluteUrl("${settings.url}/", message.image) + holder.image.load(url, imageLoader) { + error(R.drawable.ic_alarm) + placeholder(R.drawable.ic_placeholder) + } } val prefs = PreferenceManager.getDefaultSharedPreferences(context) 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 f2f95f80..006a9810 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/MessagesActivity.kt @@ -29,6 +29,7 @@ import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import coil.request.ImageRequest import com.github.gotify.BuildConfig import com.github.gotify.MissedMessageUtil import com.github.gotify.R @@ -57,7 +58,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.navigation.NavigationView import com.google.android.material.snackbar.BaseTransientBottomBar.BaseCallback import com.google.android.material.snackbar.Snackbar -import java.io.IOException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.tinylog.kotlin.Logger @@ -102,7 +102,7 @@ internal class MessagesActivity : listMessageAdapter = ListMessageAdapter( this, viewModel.settings, - viewModel.picassoHandler.get() + viewModel.coilHandler.get() ) { message -> scheduleDeletion(message) } @@ -169,19 +169,20 @@ internal class MessagesActivity : } private fun refreshAll() { - try { - viewModel.picassoHandler.evict() - } catch (e: IOException) { - Logger.error(e, "Problem evicting Picasso cache") - } + viewModel.coilHandler.evict() startActivity(Intent(this, InitializationActivity::class.java)) finish() } private fun onRefresh() { + viewModel.coilHandler.evict() viewModel.messages.clear() launchCoroutine { - loadMore(viewModel.appId) + loadMore(viewModel.appId).forEachIndexed { index, message -> + if (message.image != null) { + listMessageAdapter.notifyItemChanged(index) + } + } } } @@ -201,15 +202,18 @@ internal class MessagesActivity : val item = menu.add(R.id.apps, index, APPLICATION_ORDER, app.name) item.isCheckable = true if (app.id == viewModel.appId) selectedItem = item - val t = Utils.toDrawable(resources) { icon -> item.icon = icon } + val t = Utils.toDrawable { icon -> item.icon = icon } viewModel.targetReferences.add(t) - viewModel.picassoHandler - .get() - .load(Utils.resolveAbsoluteUrl(viewModel.settings.url + "/", app.image)) + val request = ImageRequest.Builder(this) + .data(Utils.resolveAbsoluteUrl(viewModel.settings.url + "/", app.image)) .error(R.drawable.ic_alarm) .placeholder(R.drawable.ic_placeholder) - .resize(100, 100) - .into(t) + .size(100, 100) + .target(t) + .build() + viewModel.coilHandler + .get() + .enqueue(request) } selectAppInMenu(selectedItem) } @@ -552,11 +556,12 @@ internal class MessagesActivity : ) } - private suspend fun loadMore(appId: Long) { + private suspend fun loadMore(appId: Long): List { val messagesWithImages = viewModel.messages.loadMore(appId) withContext(Dispatchers.Main) { updateMessagesAndStopLoading(messagesWithImages) } + return messagesWithImages } private suspend fun updateMessagesForApplication(withLoadingSpinner: Boolean, appId: Long) { 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 bcd7c470..b2efcd2f 100644 --- a/app/src/main/kotlin/com/github/gotify/messages/MessagesModel.kt +++ b/app/src/main/kotlin/com/github/gotify/messages/MessagesModel.kt @@ -2,18 +2,18 @@ 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 import com.github.gotify.messages.provider.ApplicationHolder import com.github.gotify.messages.provider.MessageFacade import com.github.gotify.messages.provider.MessageState -import com.github.gotify.picasso.PicassoHandler -import com.squareup.picasso.Target internal class MessagesModel(parentView: Activity) : ViewModel() { val settings = Settings(parentView) - val picassoHandler = PicassoHandler(parentView, settings) + val coilHandler = CoilHandler(parentView, settings) val client = ClientFactory.clientToken(settings.url, settings.sslSettings(), settings.token) val appsHolder = ApplicationHolder(parentView, client) val messages = MessageFacade(client.createService(MessageApi::class.java), appsHolder) diff --git a/app/src/main/kotlin/com/github/gotify/picasso/PicassoDataRequestHandler.kt b/app/src/main/kotlin/com/github/gotify/picasso/PicassoDataRequestHandler.kt deleted file mode 100644 index 091fb6f8..00000000 --- a/app/src/main/kotlin/com/github/gotify/picasso/PicassoDataRequestHandler.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.github.gotify.picasso - -import android.graphics.BitmapFactory -import android.util.Base64 -import com.squareup.picasso.Picasso -import com.squareup.picasso.Request -import com.squareup.picasso.RequestHandler -import org.tinylog.kotlin.Logger - -/** - * Adapted from https://github.com/square/picasso/issues/1395#issuecomment-220929377 By - * https://github.com/SmartDengg - */ -internal class PicassoDataRequestHandler : RequestHandler() { - companion object { - private const val DATA_SCHEME = "data" - } - - override fun canHandleRequest(data: Request): Boolean { - val scheme = data.uri.scheme - return DATA_SCHEME.equals(scheme, ignoreCase = true) - } - - override fun load(request: Request, networkPolicy: Int): Result { - val uri = request.uri.toString() - val imageDataBytes = uri.substring(uri.indexOf(",") + 1) - val bytes = Base64.decode(imageDataBytes.toByteArray(), Base64.DEFAULT) - val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) - - if (bitmap == null) { - val show = if (uri.length > 50) uri.take(50) + "..." else uri - val malformed = RuntimeException("Malformed data uri: $show") - Logger.error(malformed, "Could not load image") - throw malformed - } - - return Result(bitmap, Picasso.LoadedFrom.NETWORK) - } -} diff --git a/app/src/main/kotlin/com/github/gotify/picasso/PicassoHandler.kt b/app/src/main/kotlin/com/github/gotify/picasso/PicassoHandler.kt deleted file mode 100644 index 0189d6aa..00000000 --- a/app/src/main/kotlin/com/github/gotify/picasso/PicassoHandler.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.github.gotify.picasso - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import com.github.gotify.R -import com.github.gotify.Settings -import com.github.gotify.Utils -import com.github.gotify.api.CertUtils -import com.github.gotify.client.model.Application -import com.squareup.picasso.OkHttp3Downloader -import com.squareup.picasso.Picasso -import java.io.File -import java.io.IOException -import okhttp3.Cache -import okhttp3.OkHttpClient -import org.tinylog.kotlin.Logger - -internal class PicassoHandler(private val context: Context, private val settings: Settings) { - companion object { - private const val PICASSO_CACHE_SIZE = 50 * 1024 * 1024 // 50 MB - private const val PICASSO_CACHE_SUBFOLDER = "picasso-cache" - } - - private val picassoCache = Cache( - File(context.cacheDir, PICASSO_CACHE_SUBFOLDER), - PICASSO_CACHE_SIZE.toLong() - ) - - private val picasso = makePicasso() - - private fun makePicasso(): Picasso { - val builder = OkHttpClient.Builder() - builder.cache(picassoCache) - CertUtils.applySslSettings(builder, settings.sslSettings()) - val downloader = OkHttp3Downloader(builder.build()) - return Picasso.Builder(context) - .addRequestHandler(PicassoDataRequestHandler()) - .downloader(downloader) - .build() - } - - @Throws(IOException::class) - fun getImageFromUrl(url: String?): Bitmap = picasso.load(url).get() - - fun getIcon(app: Application?): Bitmap { - if (app == null) { - return BitmapFactory.decodeResource(context.resources, R.drawable.gotify) - } - try { - return getImageFromUrl( - Utils.resolveAbsoluteUrl("${settings.url}/", app.image) - ) - } catch (e: IOException) { - Logger.error(e, "Could not load image for notification") - } - return BitmapFactory.decodeResource(context.resources, R.drawable.gotify) - } - - fun get() = picasso - - @Throws(IOException::class) - fun evict() { - picassoCache.evictAll() - } -} diff --git a/app/src/main/kotlin/com/github/gotify/service/WebSocketConnection.kt b/app/src/main/kotlin/com/github/gotify/service/WebSocketConnection.kt index 6b149840..b3e809c2 100644 --- a/app/src/main/kotlin/com/github/gotify/service/WebSocketConnection.kt +++ b/app/src/main/kotlin/com/github/gotify/service/WebSocketConnection.kt @@ -11,7 +11,7 @@ import com.github.gotify.client.model.Message import java.util.Calendar import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicLong -import okhttp3.HttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response @@ -89,7 +89,7 @@ internal class WebSocketConnection( } private fun request(): Request { - val url = HttpUrl.parse(baseUrl)!! + val url = baseUrl.toHttpUrlOrNull()!! .newBuilder() .addPathSegment("stream") .addQueryParameter("token", token) @@ -187,12 +187,12 @@ internal class WebSocketConnection( } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { - val code = if (response != null) "StatusCode: ${response.code()}" else "" - val message = if (response != null) response.message() else "" + val code = if (response != null) "StatusCode: ${response.code}" else "" + val message = response?.message ?: "" Logger.error(t) { "WebSocket($id): failure $code Message: $message" } syncExec(id) { closed() - if (response != null && response.code() >= 400 && response.code() <= 499) { + if (response != null && response.code >= 400 && response.code <= 499) { onBadRequest.execute(message) return@syncExec } 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 e2fc90d0..79e51a0c 100644 --- a/app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt +++ b/app/src/main/kotlin/com/github/gotify/service/WebSocketService.kt @@ -17,6 +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.MarkwonFactory import com.github.gotify.MissedMessageUtil import com.github.gotify.NotificationSupport @@ -34,7 +35,6 @@ import com.github.gotify.log.UncaughtExceptionHandler import com.github.gotify.messages.Extras import com.github.gotify.messages.IntentUrlDialogActivity import com.github.gotify.messages.MessagesActivity -import com.github.gotify.picasso.PicassoHandler import io.noties.markwon.Markwon import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicLong @@ -62,7 +62,7 @@ internal class WebSocketService : Service() { private val lastReceivedMessage = AtomicLong(NOT_LOADED) private lateinit var missingMessageUtil: MissedMessageUtil - private lateinit var picassoHandler: PicassoHandler + private lateinit var coilHandler: CoilHandler private lateinit var markwon: Markwon override fun onCreate() { @@ -75,8 +75,8 @@ internal class WebSocketService : Service() { ) missingMessageUtil = MissedMessageUtil(client.createService(MessageApi::class.java)) Logger.info("Create ${javaClass.simpleName}") - picassoHandler = PicassoHandler(this, settings) - markwon = MarkwonFactory.createForNotification(this, picassoHandler.get()) + coilHandler = CoilHandler(this, settings) + markwon = MarkwonFactory.createForNotification(this, coilHandler.get()) } override fun onDestroy() { @@ -381,7 +381,7 @@ internal class WebSocketService : Service() { .setDefaults(Notification.DEFAULT_ALL) .setWhen(System.currentTimeMillis()) .setSmallIcon(R.drawable.ic_gotify) - .setLargeIcon(picassoHandler.getIcon(appIdToApp[appId])) + .setLargeIcon(coilHandler.getIcon(appIdToApp[appId])) .setTicker("${getString(R.string.app_name)} - $title") .setGroup(NotificationSupport.Group.MESSAGES) .setContentTitle(title) @@ -410,7 +410,7 @@ internal class WebSocketService : Service() { try { b.setStyle( NotificationCompat.BigPictureStyle() - .bigPicture(picassoHandler.getImageFromUrl(notificationImageUrl)) + .bigPicture(coilHandler.getImageFromUrl(notificationImageUrl)) ) } catch (e: Exception) { Logger.error(e, "Error loading bigImageUrl")