mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-14 19:20:28 +03:00
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:
parent
7d54eef95b
commit
08e975cd8e
26 changed files with 463 additions and 91 deletions
|
|
@ -109,7 +109,7 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
|
|||
return null;
|
||||
}}
|
||||
element={
|
||||
<>
|
||||
<AuthRouteThemeManager>
|
||||
<ClientRoot>
|
||||
<ClientInitStorageAtom>
|
||||
<ClientRoomsNotificationPreferences>
|
||||
|
|
@ -132,8 +132,7 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
|
|||
</ClientRoomsNotificationPreferences>
|
||||
</ClientInitStorageAtom>
|
||||
</ClientRoot>
|
||||
<AuthRouteThemeManager />
|
||||
</>
|
||||
</AuthRouteThemeManager>
|
||||
}
|
||||
>
|
||||
<Route
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
import { useEffect } from 'react';
|
||||
import React, { ReactNode, useEffect } from 'react';
|
||||
import { configClass, varsClass } from 'folds';
|
||||
import { DarkTheme, LightTheme, ThemeKind, useSystemThemeKind, useThemes } from '../hooks/useTheme';
|
||||
import { useSetting } from '../state/hooks/settings';
|
||||
import { settingsAtom } from '../state/settings';
|
||||
import {
|
||||
DarkTheme,
|
||||
LightTheme,
|
||||
ThemeContextProvider,
|
||||
ThemeKind,
|
||||
useActiveTheme,
|
||||
useSystemThemeKind,
|
||||
} from '../hooks/useTheme';
|
||||
|
||||
export function UnAuthRouteThemeManager() {
|
||||
const systemThemeKind = useSystemThemeKind();
|
||||
|
|
@ -21,38 +26,15 @@ export function UnAuthRouteThemeManager() {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function AuthRouteThemeManager() {
|
||||
const systemThemeKind = useSystemThemeKind();
|
||||
const themes = useThemes();
|
||||
const [systemTheme] = useSetting(settingsAtom, 'useSystemTheme');
|
||||
const [themeId] = useSetting(settingsAtom, 'themeId');
|
||||
const [lightThemeId] = useSetting(settingsAtom, 'lightThemeId');
|
||||
const [darkThemeId] = useSetting(settingsAtom, 'darkThemeId');
|
||||
export function AuthRouteThemeManager({ children }: { children: ReactNode }) {
|
||||
const activeTheme = useActiveTheme();
|
||||
|
||||
// apply normal theme if system theme is disabled
|
||||
useEffect(() => {
|
||||
if (!systemTheme) {
|
||||
document.body.className = '';
|
||||
document.body.classList.add(configClass, varsClass);
|
||||
const selectedTheme = themes.find((theme) => theme.id === themeId) ?? LightTheme;
|
||||
document.body.className = '';
|
||||
document.body.classList.add(configClass, varsClass);
|
||||
|
||||
document.body.classList.add(...selectedTheme.classNames);
|
||||
}
|
||||
}, [systemTheme, themes, themeId]);
|
||||
document.body.classList.add(...activeTheme.classNames);
|
||||
}, [activeTheme]);
|
||||
|
||||
// apply preferred system theme if system theme is enabled
|
||||
useEffect(() => {
|
||||
if (systemTheme) {
|
||||
document.body.className = '';
|
||||
document.body.classList.add(configClass, varsClass);
|
||||
const selectedTheme =
|
||||
systemThemeKind === ThemeKind.Dark
|
||||
? themes.find((theme) => theme.id === darkThemeId) ?? DarkTheme
|
||||
: themes.find((theme) => theme.id === lightThemeId) ?? LightTheme;
|
||||
|
||||
document.body.classList.add(...selectedTheme.classNames);
|
||||
}
|
||||
}, [systemTheme, systemThemeKind, themes, lightThemeId, darkThemeId]);
|
||||
|
||||
return null;
|
||||
return <ThemeContextProvider value={activeTheme}>{children}</ThemeContextProvider>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
|
||||
import { RoomProvider } from '../../../hooks/useRoom';
|
||||
import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { JoinBeforeNavigate } from '../../../features/join-before-navigate';
|
||||
import { useDirectRooms } from './useDirectRooms';
|
||||
|
|
@ -20,7 +20,7 @@ export function DirectRouteRoomProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
return (
|
||||
<RoomProvider key={room.roomId} value={room}>
|
||||
{children}
|
||||
<IsDirectRoomProvider value>{children}</IsDirectRoomProvider>
|
||||
</RoomProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
|
||||
import { RoomProvider } from '../../../hooks/useRoom';
|
||||
import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { JoinBeforeNavigate } from '../../../features/join-before-navigate';
|
||||
import { useHomeRooms } from './useHomeRooms';
|
||||
|
|
@ -28,7 +28,7 @@ export function HomeRouteRoomProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
return (
|
||||
<RoomProvider key={room.roomId} value={room}>
|
||||
{children}
|
||||
<IsDirectRoomProvider value={false}>{children}</IsDirectRoomProvider>
|
||||
</RoomProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ import {
|
|||
Reply,
|
||||
Time,
|
||||
Username,
|
||||
UsernameBold,
|
||||
} from '../../../components/message';
|
||||
import colorMXID from '../../../../util/colorMXID';
|
||||
import {
|
||||
factoryRenderLinkifyWithMention,
|
||||
getReactCustomHtmlParser,
|
||||
|
|
@ -84,6 +84,16 @@ import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
|||
import { BackRouteHandler } from '../../../components/BackRouteHandler';
|
||||
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
|
||||
import { allRoomsAtom } from '../../../state/room-list/roomList';
|
||||
import { usePowerLevels, usePowerLevelsAPI } from '../../../hooks/usePowerLevels';
|
||||
import {
|
||||
getTagIconSrc,
|
||||
useAccessibleTagColors,
|
||||
usePowerLevelTags,
|
||||
} from '../../../hooks/usePowerLevelTags';
|
||||
import { useTheme } from '../../../hooks/useTheme';
|
||||
import { PowerIcon } from '../../../components/power';
|
||||
import colorMXID from '../../../../util/colorMXID';
|
||||
import { mDirectAtom } from '../../../state/mDirectList';
|
||||
|
||||
type RoomNotificationsGroup = {
|
||||
roomId: string;
|
||||
|
|
@ -194,6 +204,7 @@ type RoomNotificationsGroupProps = {
|
|||
urlPreview?: boolean;
|
||||
hideActivity: boolean;
|
||||
onOpen: (roomId: string, eventId: string) => void;
|
||||
legacyUsernameColor?: boolean;
|
||||
};
|
||||
function RoomNotificationsGroupComp({
|
||||
room,
|
||||
|
|
@ -202,10 +213,18 @@ function RoomNotificationsGroupComp({
|
|||
urlPreview,
|
||||
hideActivity,
|
||||
onOpen,
|
||||
legacyUsernameColor,
|
||||
}: RoomNotificationsGroupProps) {
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||
|
||||
const powerLevels = usePowerLevels(room);
|
||||
const { getPowerLevel } = usePowerLevelsAPI(powerLevels);
|
||||
const [powerLevelTags, getPowerLevelTag] = usePowerLevelTags(room, powerLevels);
|
||||
const theme = useTheme();
|
||||
const accessibleTagColors = useAccessibleTagColors(theme.kind, powerLevelTags);
|
||||
|
||||
const mentionClickHandler = useMentionClickHandler(room.roomId);
|
||||
const spoilerClickHandler = useSpoilerClickHandler();
|
||||
|
||||
|
|
@ -424,6 +443,17 @@ function RoomNotificationsGroupComp({
|
|||
const threadRootId =
|
||||
relation?.rel_type === RelationType.Thread ? relation.event_id : undefined;
|
||||
|
||||
const senderPowerLevel = getPowerLevel(event.sender);
|
||||
const powerLevelTag = getPowerLevelTag(senderPowerLevel);
|
||||
const tagColor = powerLevelTag?.color
|
||||
? accessibleTagColors?.get(powerLevelTag.color)
|
||||
: undefined;
|
||||
const tagIconSrc = powerLevelTag?.icon
|
||||
? getTagIconSrc(mx, useAuthentication, powerLevelTag.icon)
|
||||
: undefined;
|
||||
|
||||
const usernameColor = legacyUsernameColor ? colorMXID(event.sender) : tagColor;
|
||||
|
||||
return (
|
||||
<SequenceCard
|
||||
key={notification.event.event_id}
|
||||
|
|
@ -458,11 +488,14 @@ function RoomNotificationsGroupComp({
|
|||
>
|
||||
<Box gap="300" justifyContent="SpaceBetween" alignItems="Center" grow="Yes">
|
||||
<Box gap="200" alignItems="Baseline">
|
||||
<Username style={{ color: colorMXID(event.sender) }}>
|
||||
<Text as="span" truncate>
|
||||
<b>{displayName}</b>
|
||||
</Text>
|
||||
</Username>
|
||||
<Box alignItems="Center" gap="200">
|
||||
<Username style={{ color: usernameColor }}>
|
||||
<Text as="span" truncate>
|
||||
<UsernameBold>{displayName}</UsernameBold>
|
||||
</Text>
|
||||
</Username>
|
||||
{tagIconSrc && <PowerIcon size="100" iconSrc={tagIconSrc} />}
|
||||
</Box>
|
||||
<Time ts={event.origin_server_ts} />
|
||||
</Box>
|
||||
<Box shrink="No" gap="200" alignItems="Center">
|
||||
|
|
@ -482,6 +515,10 @@ function RoomNotificationsGroupComp({
|
|||
replyEventId={replyEventId}
|
||||
threadRootId={threadRootId}
|
||||
onClick={handleOpenClick}
|
||||
getPowerLevel={getPowerLevel}
|
||||
getPowerLevelTag={getPowerLevelTag}
|
||||
accessibleTagColors={accessibleTagColors}
|
||||
legacyUsernameColor={legacyUsernameColor}
|
||||
/>
|
||||
)}
|
||||
{renderMatrixEvent(event.type, false, event, displayName, getContent)}
|
||||
|
|
@ -511,7 +548,9 @@ export function Notifications() {
|
|||
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
|
||||
const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
|
||||
const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor');
|
||||
const screenSize = useScreenSizeContext();
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
|
||||
const { navigateRoom } = useRoomNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
|
@ -671,6 +710,9 @@ export function Notifications() {
|
|||
urlPreview={urlPreview}
|
||||
hideActivity={hideActivity}
|
||||
onOpen={navigateRoom}
|
||||
legacyUsernameColor={
|
||||
legacyUsernameColor || mDirects.has(groupRoom.roomId)
|
||||
}
|
||||
/>
|
||||
</VirtualTile>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { ReactNode } from 'react';
|
|||
import { useParams } from 'react-router-dom';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
|
||||
import { RoomProvider } from '../../../hooks/useRoom';
|
||||
import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { JoinBeforeNavigate } from '../../../features/join-before-navigate';
|
||||
import { useSpace } from '../../../hooks/useSpace';
|
||||
|
|
@ -10,11 +10,13 @@ import { getAllParents } from '../../../utils/room';
|
|||
import { roomToParentsAtom } from '../../../state/room/roomToParents';
|
||||
import { allRoomsAtom } from '../../../state/room-list/roomList';
|
||||
import { useSearchParamsViaServers } from '../../../hooks/router/useSearchParamsViaServers';
|
||||
import { mDirectAtom } from '../../../state/mDirectList';
|
||||
|
||||
export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) {
|
||||
const mx = useMatrixClient();
|
||||
const space = useSpace();
|
||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const allRooms = useAtomValue(allRoomsAtom);
|
||||
|
||||
const { roomIdOrAlias, eventId } = useParams();
|
||||
|
|
@ -39,7 +41,7 @@ export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
return (
|
||||
<RoomProvider key={room.roomId} value={room}>
|
||||
{children}
|
||||
<IsDirectRoomProvider value={mDirects.has(room.roomId)}>{children}</IsDirectRoomProvider>
|
||||
</RoomProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue