feat: add user color customization and metadata handling

- Implemented `useUserColor` hook to manage user profile color stored in avatar PNG metadata.
- Added `useOtherUserColor` hook to fetch and cache colors from other users' avatars.
- Created utility functions for reading and writing PNG metadata, enabling color embedding and extraction.
- Refactored `SearchResultGroup`, `RoomInput`, `Message`, `RoomPinMenu`, and `Notifications` components to utilize user color for display.
- Introduced `UserColorPicker` component in settings for users to select and save their profile color.
- Enhanced notification and message rendering to prioritize custom user colors over legacy colors.
This commit is contained in:
2026-02-06 05:53:37 +11:00
parent 4ca4af0e8b
commit 516000a25f
11 changed files with 1061 additions and 222 deletions

View File

@@ -86,6 +86,7 @@ import {
useGetMemberPowerTag,
} from '../../../hooks/useMemberPowerTag';
import { useRoomCreatorsTag } from '../../../hooks/useRoomCreatorsTag';
import { useOtherUserColor } from '../../../hooks/useUserColor';
type PinnedMessageProps = {
room: Room;
@@ -179,6 +180,9 @@ function PinnedMessage({
const senderAvatarMxc = getMemberAvatarMxc(room, sender);
const getContent = (() => pinnedEvent.getContent()) as GetContentCallback;
// Get custom user color from avatar metadata
const customUserColor = useOtherUserColor(sender, senderAvatarMxc);
const memberPowerTag = getMemberPowerTag(sender);
const tagColor = memberPowerTag?.color
? accessibleTagColors?.get(memberPowerTag.color)
@@ -187,7 +191,8 @@ function PinnedMessage({
? getPowerTagIconSrc(mx, useAuthentication, memberPowerTag.icon)
: undefined;
const usernameColor = legacyUsernameColor ? colorMXID(sender) : tagColor;
// Priority: custom user color > tag color (non-legacy) > colorMXID (legacy)
const usernameColor = customUserColor ?? (legacyUsernameColor ? colorMXID(sender) : tagColor);
return (
<ModernLayout