Fix room icons not rendering on iOS (#361)

Co-authored-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social>
This commit is contained in:
Aditya Chaudhary 2026-08-13 18:09:01 +00:00 committed by hodlbod
parent f411973409
commit 84fee9de18

View file

@ -6,7 +6,6 @@
</style> </style>
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte"
import {maybe} from "@welshman/lib" import {maybe} from "@welshman/lib"
const { const {
@ -22,46 +21,63 @@
const px = size * 4 const px = size * 4
const isSafari = // The ios app's wkwebview has no "Safari" token in its user agent, so
// detect the engine instead of sniffing for the Safari browser.
const isWebkit =
typeof navigator !== "undefined" && typeof navigator !== "undefined" &&
/safari/i.test(navigator.userAgent) && /applewebkit/i.test(navigator.userAgent) &&
!/chrome|chromium|android/i.test(navigator.userAgent) !/chrome|chromium|android|firefox/i.test(navigator.userAgent)
// Strip any query string/fragment - hosted icons are often served with one.
const isRemoteSvg = (value: string) =>
!value.startsWith("data:") && /\.svg$/i.test(value.split(/[?#]/)[0]!)
let canceled = false
let objectUrl = $state(maybe<string>()) let objectUrl = $state(maybe<string>())
const src = $derived(objectUrl || icon) const src = $derived(objectUrl || icon)
// Primal issues 302 redirects from blossom, which messes up safari // Primal issues 302 redirects from blossom, which breaks mask-image on webkit.
const fetchSvg = async () => { const fetchSvg = async (url: string) => {
try { try {
const response = await fetch(icon, { const response = await fetch(url, {
mode: "cors", mode: "cors",
credentials: "omit", credentials: "omit",
}) })
if (response.ok) { if (response.ok) {
const blob = await response.blob() return URL.createObjectURL(await response.blob())
if (!canceled) {
objectUrl = URL.createObjectURL(blob)
}
} }
} catch { } catch {
// pass // pass
} }
} }
onMount(() => { // Re-fetch when icon changes, revoking the previous blob url.
if (isSafari && icon.toLowerCase().endsWith(".svg")) { $effect(() => {
fetchSvg() const url = icon
let canceled = false
let created: string | undefined
if (isWebkit && isRemoteSvg(url)) {
fetchSvg(url).then(blobUrl => {
if (!blobUrl) return
if (canceled) {
URL.revokeObjectURL(blobUrl)
} else {
created = blobUrl
objectUrl = blobUrl
}
})
} }
return () => { return () => {
canceled = true canceled = true
if (objectUrl) { if (created) {
URL.revokeObjectURL(objectUrl) URL.revokeObjectURL(created)
objectUrl = undefined
} }
} }
}) })