forked from github/cinny
🦉 additional reaction chip left
This commit is contained in:
@@ -79,6 +79,7 @@ import { MemberPowerTag, StateEvent } from '../../../../types/matrix/room';
|
||||
import { PowerIcon } from '../../../components/power';
|
||||
import colorMXID from '../../../../util/colorMXID';
|
||||
import { getPowerTagIconSrc } from '../../../hooks/useMemberPowerTag';
|
||||
import { AddReactionButton } from '../../../../owl/components/AddReactionButton';
|
||||
|
||||
export type ReactionHandler = (keyOrMxc: string, shortcode: string) => void;
|
||||
|
||||
@@ -813,6 +814,15 @@ export const Message = as<'div', MessageProps>(
|
||||
</AvatarBase>
|
||||
);
|
||||
|
||||
const visibleReactions = relations?.getSortedAnnotationsByKey();
|
||||
const hasVisibleReactions = !!visibleReactions && visibleReactions.some(
|
||||
([key, events]) => typeof key === 'string' && Array.from(events).length > 0
|
||||
);
|
||||
|
||||
const handleInlineAddReaction: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||
setEmojiBoardAnchor(evt.currentTarget.getBoundingClientRect());
|
||||
};
|
||||
|
||||
const msgContentJSX = (
|
||||
<Box direction="Column" alignSelf="Start" style={{ maxWidth: '100%' }}>
|
||||
{reply}
|
||||
@@ -831,7 +841,11 @@ export const Message = as<'div', MessageProps>(
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
{reactions}
|
||||
{reactions && React.isValidElement(reactions)
|
||||
? React.cloneElement(reactions as React.ReactElement<any>, {
|
||||
onAddReaction: handleInlineAddReaction,
|
||||
})
|
||||
: reactions}
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1129,6 +1143,11 @@ export const Message = as<'div', MessageProps>(
|
||||
</Menu>
|
||||
</div>
|
||||
)}
|
||||
{!edit && collapse && canSendReaction && !hasVisibleReactions
|
||||
&& messageLayout !== MessageLayout.Compact
|
||||
&& (hover || !!emojiBoardAnchor) && (
|
||||
<AddReactionButton onClick={handleInlineAddReaction} ghost />
|
||||
)}
|
||||
{messageLayout === MessageLayout.Compact && (
|
||||
<CompactLayout before={headerJSX} onContextMenu={handleContextMenu}>
|
||||
{msgContentJSX}
|
||||
|
||||
@@ -23,6 +23,7 @@ import * as css from './styles.css';
|
||||
import { ReactionViewer } from '../reaction-viewer';
|
||||
import { stopPropagation } from '../../../utils/keyboard';
|
||||
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
|
||||
import { AddReactionButton } from '../../../../owl/components/AddReactionButton';
|
||||
|
||||
export type ReactionsProps = {
|
||||
room: Room;
|
||||
@@ -30,9 +31,10 @@ export type ReactionsProps = {
|
||||
canSendReaction?: boolean;
|
||||
relations: Relations;
|
||||
onReactionToggle: (targetEventId: string, key: string, shortcode?: string) => void;
|
||||
onAddReaction?: MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
export const Reactions = as<'div', ReactionsProps>(
|
||||
({ className, room, relations, mEventId, canSendReaction, onReactionToggle, ...props }, ref) => {
|
||||
({ className, room, relations, mEventId, canSendReaction, onReactionToggle, onAddReaction, ...props }, ref) => {
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const [viewer, setViewer] = useState<boolean | string>(false);
|
||||
@@ -41,6 +43,9 @@ export const Reactions = as<'div', ReactionsProps>(
|
||||
relations,
|
||||
useCallback((rel) => [...(rel.getSortedAnnotationsByKey() ?? [])], [])
|
||||
);
|
||||
const visibleCount = reactions.filter(
|
||||
([key, events]) => typeof key === 'string' && Array.from(events).length > 0
|
||||
).length;
|
||||
|
||||
const handleViewReaction: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||
evt.stopPropagation();
|
||||
@@ -94,7 +99,10 @@ export const Reactions = as<'div', ReactionsProps>(
|
||||
</TooltipProvider>
|
||||
);
|
||||
})}
|
||||
{reactions.length > 0 && (
|
||||
{visibleCount > 0 && canSendReaction && onAddReaction && (
|
||||
<AddReactionButton onClick={onAddReaction} />
|
||||
)}
|
||||
{visibleCount > 0 && (
|
||||
<Overlay
|
||||
onContextMenu={(evt: any) => {
|
||||
evt.stopPropagation();
|
||||
|
||||
23
src/owl/components/AddReactionButton.tsx
Normal file
23
src/owl/components/AddReactionButton.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React, { MouseEventHandler } from 'react';
|
||||
import { Box, Icon, Icons } from 'folds';
|
||||
import * as css from '../styles/reactions.css';
|
||||
|
||||
type AddReactionButtonProps = {
|
||||
onClick: MouseEventHandler<HTMLButtonElement>;
|
||||
ghost?: boolean;
|
||||
};
|
||||
|
||||
export function AddReactionButton({ onClick, ghost }: AddReactionButtonProps) {
|
||||
return (
|
||||
<Box
|
||||
as="button"
|
||||
className={ghost ? css.AddReactionGhost : css.AddReactionChip}
|
||||
alignItems="Center"
|
||||
justifyContent="Center"
|
||||
shrink="No"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Icon src={Icons.SmilePlus} size="50" />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
41
src/owl/styles/reactions.css.ts
Normal file
41
src/owl/styles/reactions.css.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
import { DefaultReset, FocusOutline, color, config, toRem } from 'folds';
|
||||
|
||||
const addReactionBase = {
|
||||
padding: `${toRem(2)} ${config.space.S200}`,
|
||||
backgroundColor: color.SurfaceVariant.Container,
|
||||
border: `${config.borderWidth.B300} solid ${color.SurfaceVariant.ContainerLine}`,
|
||||
borderRadius: config.radii.R300,
|
||||
cursor: 'pointer',
|
||||
selectors: {
|
||||
'&:hover, &:focus-visible': {
|
||||
backgroundColor: color.SurfaceVariant.ContainerHover,
|
||||
opacity: 1,
|
||||
},
|
||||
'&:active': {
|
||||
backgroundColor: color.SurfaceVariant.ContainerActive,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const AddReactionChip = style([
|
||||
DefaultReset,
|
||||
FocusOutline,
|
||||
{
|
||||
...addReactionBase,
|
||||
opacity: 0.6,
|
||||
},
|
||||
]);
|
||||
|
||||
export const AddReactionGhost = style([
|
||||
DefaultReset,
|
||||
FocusOutline,
|
||||
{
|
||||
...addReactionBase,
|
||||
position: 'absolute',
|
||||
left: config.space.S400,
|
||||
bottom: config.space.S100,
|
||||
opacity: 0.5,
|
||||
zIndex: 1,
|
||||
},
|
||||
]);
|
||||
Reference in New Issue
Block a user