|
| 1 | +/** |
| 2 | + * Returns true if the username looks like a Matrix user ID (@localpart:homeserver.tld). |
| 3 | + * @param {string} username |
| 4 | + * @returns {boolean} |
| 5 | + */ |
| 6 | +export const isMatrixUser = (username) => { |
| 7 | + if (!username) return false; |
| 8 | + return /^@[^:]+:[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(username); |
| 9 | +}; |
| 10 | + |
| 11 | +/** |
| 12 | + * Parses a Matrix user ID into localpart and homeserver. |
| 13 | + * @param {string} matrixId e.g. "@alice:matrix.org" |
| 14 | + * @returns {{ localpart: string, homeserver: string } | null} |
| 15 | + */ |
| 16 | +export const parseMatrixUserId = (matrixId) => { |
| 17 | + if (!isMatrixUser(matrixId)) return null; |
| 18 | + const withoutAt = matrixId.slice(1); |
| 19 | + const colonIdx = withoutAt.indexOf(':'); |
| 20 | + return { |
| 21 | + localpart: withoutAt.slice(0, colonIdx), |
| 22 | + homeserver: withoutAt.slice(colonIdx + 1), |
| 23 | + }; |
| 24 | +}; |
| 25 | + |
| 26 | +/** |
| 27 | + * Returns a display-friendly label, truncating long homeservers. |
| 28 | + * @param {string} matrixId |
| 29 | + * @returns {string} |
| 30 | + */ |
| 31 | +export const getMatrixDisplayLabel = (matrixId) => { |
| 32 | + const parsed = parseMatrixUserId(matrixId); |
| 33 | + if (!parsed) return matrixId; |
| 34 | + const { localpart, homeserver } = parsed; |
| 35 | + const shortHost = |
| 36 | + homeserver.length > 20 ? homeserver.slice(0, 18) + '…' : homeserver; |
| 37 | + return `@${localpart}:${shortHost}`; |
| 38 | +}; |
| 39 | + |
| 40 | +/** |
| 41 | + * Returns 1-2 char initials for avatar fallback. |
| 42 | + * @param {string} matrixId |
| 43 | + * @returns {string} |
| 44 | + */ |
| 45 | +export const getMatrixInitials = (matrixId) => { |
| 46 | + const parsed = parseMatrixUserId(matrixId); |
| 47 | + if (!parsed) return '?'; |
| 48 | + return parsed.localpart.slice(0, 2).toUpperCase(); |
| 49 | +}; |
| 50 | + |
| 51 | +/** |
| 52 | + * Generates a deterministic background color from a string. |
| 53 | + * @param {string} str |
| 54 | + * @returns {string} |
| 55 | + */ |
| 56 | +export const getAvatarColor = (str) => { |
| 57 | + const COLORS = [ |
| 58 | + '#e57373', '#f06292', '#ba68c8', '#9575cd', |
| 59 | + '#7986cb', '#64b5f6', '#4fc3f7', '#4dd0e1', |
| 60 | + '#4db6ac', '#81c784', '#aed581', '#ffd54f', |
| 61 | + '#ffb74d', '#ff8a65', '#a1887f', '#90a4ae', |
| 62 | + ]; |
| 63 | + let hash = 0; |
| 64 | + for (let i = 0; i < str.length; i++) { |
| 65 | + hash = str.charCodeAt(i) + ((hash << 5) - hash); |
| 66 | + } |
| 67 | + return COLORS[Math.abs(hash) % COLORS.length]; |
| 68 | +}; |
0 commit comments