mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-10-06 13:40:16 +08:00
Merge 7a2e9711f4
into a15d84e0ce
This commit is contained in:
commit
c127ebbf96
4 changed files with 48 additions and 61 deletions
|
@ -350,14 +350,20 @@ key {
|
|||
line-height: 1em;
|
||||
font-size: var(--size);
|
||||
border-radius: 100%;
|
||||
background-position: center center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
grid-column: 1/2;
|
||||
grid-row: 1/2;
|
||||
place-self: center center;
|
||||
display: grid;
|
||||
place-content: center center;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
z-index: 1; //place above the loading spinner
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
|
|
|
@ -51,6 +51,7 @@ import * as Cookies from "./cookies";
|
|||
import "./elements/psa";
|
||||
import "./utils/url-handler";
|
||||
import "./modals/last-signed-out-result";
|
||||
import { addToGlobal } from "./utils/global";
|
||||
|
||||
// Lock Math.random
|
||||
Object.defineProperty(Math, "random", {
|
||||
|
@ -71,13 +72,6 @@ Object.defineProperty(window, "Math", {
|
|||
enumerable: true,
|
||||
});
|
||||
|
||||
function addToGlobal(items: Record<string, unknown>): void {
|
||||
for (const [name, item] of Object.entries(items)) {
|
||||
//@ts-expect-error dev
|
||||
window[name] = item;
|
||||
}
|
||||
}
|
||||
|
||||
void loadFromLocalStorage();
|
||||
void VersionButton.update();
|
||||
Focus.set(true, true);
|
||||
|
|
|
@ -1,29 +1,40 @@
|
|||
const cachedAvatarUrlByAvatarId: Map<string, string | null> = new Map();
|
||||
import { addToGlobal } from "./global";
|
||||
|
||||
type Options = { size?: number; userIcon?: string };
|
||||
|
||||
function buildElement(
|
||||
url: string | null,
|
||||
options?: { loading?: boolean } & Options
|
||||
): HTMLElement {
|
||||
const knownBadUrls = new Set();
|
||||
|
||||
function buildElement(url: string | null, options?: Options): HTMLElement {
|
||||
const avatar = document.createElement("div");
|
||||
avatar.classList.add("avatar");
|
||||
if (url === null) {
|
||||
if (options?.loading) {
|
||||
avatar.innerHTML = `<div class="loading"><i class="fas fa-circle-notch fa-spin"><i></div>`;
|
||||
} else {
|
||||
avatar.innerHTML = `<div class="userIcon"><i class="${
|
||||
options?.userIcon ?? "fas fa-user-circle"
|
||||
}"><i></div>`;
|
||||
}
|
||||
|
||||
if (url === null || knownBadUrls.has(url)) {
|
||||
avatar.innerHTML = `<div class="userIcon"><i class="${
|
||||
options?.userIcon ?? "fas fa-user-circle"
|
||||
}"></i></div>`;
|
||||
} else {
|
||||
avatar.innerHTML = `<div class="discordImage" style="background-image:url(${url}?size=${
|
||||
options?.size ?? 32
|
||||
})"></div>`;
|
||||
avatar.innerHTML = `
|
||||
<div class="loading"><i class="fas fa-circle-notch fa-spin"></i></div>
|
||||
<div class="discordImage">
|
||||
<img src="${url}?size=${options?.size ?? 32})"
|
||||
onload="onAvatarLoaded(this)" onerror="onAvatarError(this)"
|
||||
></img>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
addToGlobal({
|
||||
onAvatarLoaded: (element: HTMLImageElement): void => {
|
||||
element.closest(".avatar")?.querySelector(".loading")?.remove();
|
||||
},
|
||||
onAvatarError: (element: HTMLImageElement): void => {
|
||||
knownBadUrls.add(element.src.split("?")[0]);
|
||||
element.closest(".avatar")?.replaceWith(buildElement(null));
|
||||
},
|
||||
});
|
||||
|
||||
export function getAvatarElement(
|
||||
{
|
||||
discordId,
|
||||
|
@ -43,40 +54,10 @@ export function getAvatarElement(
|
|||
return buildElement(null, options);
|
||||
}
|
||||
|
||||
const cachedUrl = cachedAvatarUrlByAvatarId.get(discordAvatar);
|
||||
const element = buildElement(
|
||||
`https://cdn.discordapp.com/avatars/${discordId}/${discordAvatar}.png`,
|
||||
options
|
||||
);
|
||||
|
||||
if (cachedUrl !== undefined) {
|
||||
return buildElement(cachedUrl, options);
|
||||
} else {
|
||||
const element = buildElement(null, { loading: true });
|
||||
|
||||
void getDiscordAvatarUrl({ discordId, discordAvatar }).then((url) => {
|
||||
cachedAvatarUrlByAvatarId.set(discordAvatar, url);
|
||||
element.replaceWith(buildElement(url, options));
|
||||
});
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
async function getDiscordAvatarUrl({
|
||||
discordId,
|
||||
discordAvatar,
|
||||
}: {
|
||||
discordId: string;
|
||||
discordAvatar: string;
|
||||
}): Promise<string | null> {
|
||||
// An invalid request to this URL will return a 404.
|
||||
try {
|
||||
const avatarUrl = `https://cdn.discordapp.com/avatars/${discordId}/${discordAvatar}.png`;
|
||||
|
||||
const response = await fetch(avatarUrl, { method: "HEAD" });
|
||||
if (!response.ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return avatarUrl;
|
||||
} catch (error) {}
|
||||
|
||||
return null;
|
||||
return element;
|
||||
}
|
||||
|
|
6
frontend/src/ts/utils/global.ts
Normal file
6
frontend/src/ts/utils/global.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export function addToGlobal(items: Record<string, unknown>): void {
|
||||
for (const [name, item] of Object.entries(items)) {
|
||||
//@ts-expect-error dev
|
||||
window[name] = item;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue