In some circumstances (like the server only being reachable over IPv6)
reconnecting when the network becomes available doesn't work. This due
to the network only being "partially" available (in the example: IPv4
working, but IPv6 not yet). By also listening for changes of the link
properties a new connection attempt is made when for example the IP
addresses of the link, or the networking routes change. Meaning that the
example issue is fixed, as a new attempt is made after the IPv6 address
is set on the link / the routes for IPv6 networking are available.
We only want to do the reconnect if the previous command was the
schedule reconnect, if the websocket connection got started another way
or was closed, we don't want to do the reconnect.
When receiving a message with the same image in the markdown body and in
the extras client::notification.bigImageUrl, then there is a clash on
the file system.
One request succeeds and the other fails with the following error. This
commit ensures that there is only one coil image loader instance, so
that there shouldn't be file system race conditions.
WebSocket(1): received message {"id":845,"appid":21,...}
Failed - http://192.168.178.2:8000/1.jpg?v=1718369188 - java.lang.IllegalStateException: closed
java.lang.IllegalStateException: closed
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.kt:466)
at okio.RealBufferedSource.rangeEquals(RealBufferedSource.kt:130)
at coil.decode.SvgDecodeUtils.isSvg(DecodeUtils.kt:19)
at coil.decode.SvgDecoder$Factory.isApplicable(SvgDecoder.kt:104)
at coil.decode.SvgDecoder$Factory.create(SvgDecoder.kt:99)
at coil.ComponentRegistry.newDecoder(ComponentRegistry.kt:100)
at coil.intercept.EngineInterceptor.decode(EngineInterceptor.kt:197)
at coil.intercept.EngineInterceptor.access$decode(EngineInterceptor.kt:42)
at coil.intercept.EngineInterceptor$execute$executeResult$1.invokeSuspend(EngineInterceptor.kt:131)
at coil.intercept.EngineInterceptor$execute$executeResult$1.invoke(EngineInterceptor.kt)
at coil.intercept.EngineInterceptor$execute$executeResult$1.invoke(EngineInterceptor.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:167)
at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
at coil.intercept.EngineInterceptor.execute(EngineInterceptor.kt:130)
at coil.intercept.EngineInterceptor.access$execute(EngineInterceptor.kt:42)
at coil.intercept.EngineInterceptor$execute$1.invokeSuspend(EngineInterceptor.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Successful (NETWORK) - http://192.168.178.2:8000/1.jpg?v=1718369188