Change username color in chat with power level color (#2282)

* add active theme context

* add chroma js library

* add hook for accessible tag color

* disable reply user color - temporary

* render user color based on tag in room timeline

* remove default tag icons

* move accessible color function to plugins

* render user power color in reply

* increase username weight in timeline

* add default color for member power level tag

* show red slash in power color badge with no color

* show power level color in room input reply

* show power level username color in notifications

* show power level color in notification reply

* show power level color in message search

* render power level color in room pin menu

* add toggle for legacy username colors

* drop over saturation from member default color

* change border color of power color badge

* show legacy username color in direct rooms
This commit is contained in:
Ajay Bura 2025-03-23 22:09:29 +11:00 committed by GitHub
parent 7d54eef95b
commit 08e975cd8e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 463 additions and 91 deletions

View file

@ -99,7 +99,6 @@ import {
getImageMsgContent,
getVideoMsgContent,
} from './msgContent';
import colorMXID from '../../../util/colorMXID';
import { getMemberDisplayName, getMentionContent, trimReplyFromBody } from '../../utils/room';
import { CommandAutocomplete } from './CommandAutocomplete';
import { Command, SHRUG, TABLEFLIP, UNFLIP, useCommands } from '../../hooks/useCommands';
@ -109,26 +108,44 @@ import { ReplyLayout, ThreadIndicator } from '../../components/message';
import { roomToParentsAtom } from '../../state/room/roomToParents';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useImagePackRooms } from '../../hooks/useImagePackRooms';
import { GetPowerLevelTag } from '../../hooks/usePowerLevelTags';
import { powerLevelAPI, usePowerLevelsContext } from '../../hooks/usePowerLevels';
import colorMXID from '../../../util/colorMXID';
import { useIsDirectRoom } from '../../hooks/useRoom';
interface RoomInputProps {
editor: Editor;
fileDropContainerRef: RefObject<HTMLElement>;
roomId: string;
room: Room;
getPowerLevelTag: GetPowerLevelTag;
accessibleTagColors: Map<string, string>;
}
export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
({ editor, fileDropContainerRef, roomId, room }, ref) => {
({ editor, fileDropContainerRef, roomId, room, getPowerLevelTag, accessibleTagColors }, ref) => {
const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication();
const [enterForNewline] = useSetting(settingsAtom, 'enterForNewline');
const [isMarkdown] = useSetting(settingsAtom, 'isMarkdown');
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor');
const direct = useIsDirectRoom();
const commands = useCommands(mx, room);
const emojiBtnRef = useRef<HTMLButtonElement>(null);
const roomToParents = useAtomValue(roomToParentsAtom);
const powerLevels = usePowerLevelsContext();
const [msgDraft, setMsgDraft] = useAtom(roomIdToMsgDraftAtomFamily(roomId));
const [replyDraft, setReplyDraft] = useAtom(roomIdToReplyDraftAtomFamily(roomId));
const replyUserID = replyDraft?.userId;
const replyPowerTag = getPowerLevelTag(powerLevelAPI.getPowerLevel(powerLevels, replyUserID));
const replyPowerColor = replyPowerTag.color
? accessibleTagColors.get(replyPowerTag.color)
: undefined;
const replyUsernameColor =
legacyUsernameColor || direct ? colorMXID(replyUserID ?? '') : replyPowerColor;
const [uploadBoard, setUploadBoard] = useState(true);
const [selectedFiles, setSelectedFiles] = useAtom(roomIdToUploadItemsAtomFamily(roomId));
const uploadFamilyObserverAtom = createUploadFamilyObserverAtom(
@ -348,7 +365,10 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
const handleKeyDown: KeyboardEventHandler = useCallback(
(evt) => {
if ((isKeyHotkey('mod+enter', evt) || (!enterForNewline && isKeyHotkey('enter', evt))) && !evt.nativeEvent.isComposing) {
if (
(isKeyHotkey('mod+enter', evt) || (!enterForNewline && isKeyHotkey('enter', evt))) &&
!evt.nativeEvent.isComposing
) {
evt.preventDefault();
submit();
}
@ -526,7 +546,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
<Box direction="Column">
{replyDraft.relation?.rel_type === RelationType.Thread && <ThreadIndicator />}
<ReplyLayout
userColor={colorMXID(replyDraft.userId)}
userColor={replyUsernameColor}
username={
<Text size="T300" truncate>
<b>