Fix room icons not rendering on iOS (#361)
Co-authored-by: Aditya Chaudhary <30+useradityaa@noreply.coracle.social>
This commit is contained in:
parent
f411973409
commit
84fee9de18
1 changed files with 34 additions and 18 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue