import { useEffect, useState } from "react" import Client from "@/api/client.ts" import { PronounSet, UserProfile } from "@/api/types" import { ensureArray, ensureString } from "@/util/validation.ts" interface ExtendedProfileProps { profile: UserProfile | null refreshProfile: () => void client: Client userID: string } interface SetTimezoneProps { tz?: string client: Client refreshProfile: () => void } const getCurrentTimezone = () => new Intl.DateTimeFormat().resolvedOptions().timeZone const currentTimeAdjusted = (tz: string) => { try { return new Intl.DateTimeFormat("en-GB", { hour: "numeric", minute: "numeric", second: "numeric", timeZoneName: "short", timeZone: tz, }).format(new Date()) } catch { return null } } const ClockElement = ({ tz }: { tz: string }) => { const cta = currentTimeAdjusted(tz) const isValidTZ = cta !== null const [time, setTime] = useState(cta) useEffect(() => { if (!isValidTZ) { return } let interval: number | undefined const updateTime = () => setTime(currentTimeAdjusted(tz)) const timeout = setTimeout(() => { interval = setInterval(updateTime, 1000) updateTime() }, (1001 - Date.now() % 1000)) return () => interval ? clearInterval(interval) : clearTimeout(timeout) }, [tz, isValidTZ]) if (!isValidTZ) { return null } return <>
Time:
{time}
} const SetTimeZoneElement = ({ tz, client, refreshProfile }: SetTimezoneProps) => { const zones = Intl.supportedValuesOf("timeZone") const saveTz = (newTz: string) => { if (!zones.includes(newTz)) { return } client.rpc.setProfileField("us.cloke.msc4175.tz", newTz).then( () => refreshProfile(), err => { console.error("Failed to set time zone:", err) window.alert(`Failed to set time zone: ${err}`) }, ) } const defaultValue = tz || getCurrentTimezone() return <> evt.key === "Enter" && saveTz(evt.currentTarget.value)} onBlur={evt => evt.currentTarget.value !== defaultValue && saveTz(evt.currentTarget.value)} /> {zones.map((zone) => } const UserExtendedProfile = ({ profile, refreshProfile, client, userID }: ExtendedProfileProps)=> { if (!profile) { return null } const extendedProfileKeys = ["us.cloke.msc4175.tz", "io.fsky.nyx.pronouns"] const hasExtendedProfile = extendedProfileKeys.some((key) => profile[key]) if (!hasExtendedProfile && client.userID !== userID) { return null } // Explicitly only return something if the profile has the keys we're looking for. // otherwise there's an ugly and pointless
for no real reason. const pronouns = ensureArray(profile["io.fsky.nyx.pronouns"]) as PronounSet[] const userTimeZone = ensureString(profile["us.cloke.msc4175.tz"]) return
{userTimeZone && } {userID === client.userID && } {pronouns.length > 0 && <>
Pronouns:
{pronouns.map(pronounSet => ensureString(pronounSet.summary)).join(", ")}
}
} export default UserExtendedProfile