// gomuks - A Matrix client written in Go. // Copyright (C) 2024 Tulir Asokan // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import { parseMXC } from "@/util/validation.ts" import { MemberEventContent, UserID } from "./types" export const getMediaURL = (mxc?: string, encrypted: boolean = false): string | undefined => { const [server, mediaID] = parseMXC(mxc) if (!mediaID) { return undefined } return `_gomuks/media/${server}/${mediaID}?encrypted=${encrypted}` } export const getEncryptedMediaURL = (mxc?: string): string | undefined => { return getMediaURL(mxc, true) } const FALLBACK_COLOR_COUNT = 10 export const getUserColorIndex = (userID: UserID) => userID.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0) % FALLBACK_COLOR_COUNT function initFallbackColors(): string[] { const style = getComputedStyle(document.body) const output = [] for (let i = 0; i < FALLBACK_COLOR_COUNT; i++) { output.push(style.getPropertyValue(`--sender-color-${i}`)) } return output } let fallbackColors: string[] export const getUserColor = (userID: UserID) => { if (!fallbackColors) { fallbackColors = initFallbackColors() } return fallbackColors[getUserColorIndex(userID)] } // note: this should stay in sync with fallbackAvatarTemplate in cmd/gomuks.media.go function makeFallbackAvatar(backgroundColor: string, fallbackCharacter: string): string { return "data:image/svg+xml," + encodeURIComponent(` ${escapeHTMLChar(fallbackCharacter)} `) } function escapeHTMLChar(char: string): string { switch (char) { case "&": return "&" case "<": return "<" case ">": return ">" default: return char } } export const getAvatarURL = (userID: UserID, content?: Partial): string | undefined => { const fallbackCharacter = (content?.displayname?.[0]?.toUpperCase() ?? userID[1].toUpperCase()).toWellFormed() const backgroundColor = getUserColor(userID) const [server, mediaID] = parseMXC(content?.avatar_url) if (!mediaID) { return makeFallbackAvatar(backgroundColor, fallbackCharacter) } const fallback = `${backgroundColor}:${fallbackCharacter}` return `_gomuks/media/${server}/${mediaID}?encrypted=false&fallback=${encodeURIComponent(fallback)}` }