Link to profiles from message / member sidebar.

This commit is contained in:
Paul 2021-07-02 13:35:50 +01:00
parent bf1eb2c6d1
commit 7982489ab6
4 changed files with 30 additions and 19 deletions

View file

@ -14,6 +14,7 @@ import { useContext } from "preact/hooks";
import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { AppContext } from "../../../context/revoltjs/RevoltClient";
import { memo } from "preact/compat"; import { memo } from "preact/compat";
import { MessageReply } from "./attachments/MessageReply"; import { MessageReply } from "./attachments/MessageReply";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
interface Props { interface Props {
attachContext?: boolean attachContext?: boolean
@ -29,10 +30,13 @@ function Message({ attachContext, message, contrast, content: replacement, head:
// TODO: of dependencies. We only need to update on u/avatar. // TODO: of dependencies. We only need to update on u/avatar.
const user = useUser(message.author); const user = useUser(message.author);
const client = useContext(AppContext); const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const content = message.content as string; const content = message.content as string;
const head = preferHead || (message.replies && message.replies.length > 0); const head = preferHead || (message.replies && message.replies.length > 0);
const userContext = attachContext ? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) : undefined as any; // ! FIXME: tell fatal to make this type generic const userContext = attachContext ? attachContextMenu('Menu', { user: message.author, contextualChannel: message.channel }) : undefined as any; // ! FIXME: tell fatal to make this type generic
const openProfile = () => openScreen({ id: 'profile', user_id: message.author });
return ( return (
<div id={message._id}> <div id={message._id}>
@ -46,13 +50,13 @@ function Message({ attachContext, message, contrast, content: replacement, head:
onContextMenu={attachContext ? attachContextMenu('Menu', { message, contextualChannel: message.channel, queued }) : undefined}> onContextMenu={attachContext ? attachContextMenu('Menu', { message, contextualChannel: message.channel, queued }) : undefined}>
<MessageInfo> <MessageInfo>
{ head ? { head ?
<UserIcon target={user} size={36} onContextMenu={userContext} /> : <UserIcon target={user} size={36} onContextMenu={userContext} onClick={openProfile} /> :
<MessageDetail message={message} position="left" /> } <MessageDetail message={message} position="left" /> }
</MessageInfo> </MessageInfo>
<MessageContent> <MessageContent>
{ head && <span className="detail"> { head && <span className="detail">
<span className="author"> <span className="author">
<Username user={user} onContextMenu={userContext} /> <Username user={user} onContextMenu={userContext} onClick={openProfile} />
</span> </span>
<MessageDetail message={message} position="top" /> <MessageDetail message={message} position="top" />
</span> } </span> }

View file

@ -14,7 +14,7 @@ import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
import { useIntermediate } from '../../../context/intermediate/Intermediate'; import { useIntermediate } from '../../../context/intermediate/Intermediate';
import { stopPropagation } from '../../../lib/stopPropagation'; import { stopPropagation } from '../../../lib/stopPropagation';
interface CommonProps { type CommonProps = Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children' | 'as'> & {
active?: boolean active?: boolean
alert?: 'unread' | 'mention' alert?: 'unread' | 'mention'
alertCount?: number alertCount?: number
@ -26,11 +26,12 @@ type UserProps = CommonProps & {
channel?: Channels.DirectMessageChannel channel?: Channels.DirectMessageChannel
} }
export function UserButton({ active, alert, alertCount, user, context, channel }: UserProps) { export function UserButton(props: UserProps) {
const { active, alert, alertCount, user, context, channel, ...divProps } = props;
const { openScreen } = useIntermediate(); const { openScreen } = useIntermediate();
return ( return (
<div <div {...divProps}
className={classNames(styles.item, styles.user)} className={classNames(styles.item, styles.user)}
data-active={active} data-active={active}
data-alert={typeof alert === 'string'} data-alert={typeof alert === 'string'}
@ -85,7 +86,9 @@ type ChannelProps = CommonProps & {
compact?: boolean compact?: boolean
} }
export function ChannelButton({ active, alert, alertCount, channel, user, compact }: ChannelProps) { export function ChannelButton(props: ChannelProps) {
const { active, alert, alertCount, channel, user, compact, ...divProps } = props;
if (channel.channel_type === 'SavedMessages') throw "Invalid channel type."; if (channel.channel_type === 'SavedMessages') throw "Invalid channel type.";
if (channel.channel_type === 'DirectMessage') { if (channel.channel_type === 'DirectMessage') {
if (typeof user === 'undefined') throw "No user provided."; if (typeof user === 'undefined') throw "No user provided.";
@ -95,9 +98,10 @@ export function ChannelButton({ active, alert, alertCount, channel, user, compac
const { openScreen } = useIntermediate(); const { openScreen } = useIntermediate();
return ( return (
<div data-active={active} <div {...divProps}
data-active={active}
data-alert={typeof alert === 'string'} data-alert={typeof alert === 'string'}
aria-label={{}} /*TOFIX: ADD ARIA LABEL*/ aria-label={{}} /*FIXME: ADD ARIA LABEL*/
className={classNames(styles.item, { [styles.compact]: compact })} className={classNames(styles.item, { [styles.compact]: compact })}
onContextMenu={attachContextMenu('Menu', { channel: channel._id, unread: typeof channel.unread !== 'undefined' })}> onContextMenu={attachContextMenu('Menu', { channel: channel._id, unread: typeof channel.unread !== 'undefined' })}>
<ChannelIcon className={styles.avatar} target={channel} size={compact ? 24 : 32} /> <ChannelIcon className={styles.avatar} target={channel} size={compact ? 24 : 32} />
@ -138,9 +142,12 @@ type ButtonProps = CommonProps & {
compact?: boolean compact?: boolean
} }
export default function ButtonItem({ active, alert, alertCount, onClick, className, children, compact }: ButtonProps) { export default function ButtonItem(props: ButtonProps) {
const { active, alert, alertCount, onClick, className, children, compact, ...divProps } = props;
return ( return (
<div className={classNames(styles.item, { [styles.compact]: compact, [styles.normal]: !compact }, className)} <div {...divProps}
className={classNames(styles.item, { [styles.compact]: compact, [styles.normal]: !compact }, className)}
onClick={onClick} onClick={onClick}
data-active={active} data-active={active}
data-alert={typeof alert === 'string'}> data-alert={typeof alert === 'string'}>

View file

@ -8,11 +8,12 @@ import { UserButton } from "../items/ButtonItem";
import { ChannelDebugInfo } from "./ChannelDebugInfo"; import { ChannelDebugInfo } from "./ChannelDebugInfo";
import { Channels, Servers, Users } from "revolt.js/dist/api/objects"; import { Channels, Servers, Users } from "revolt.js/dist/api/objects";
import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase"; import { GenericSidebarBase, GenericSidebarList } from "../SidebarBase";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications"; import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
import { AppContext, ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient";
import { HookContext, useChannel, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks"; import { HookContext, useChannel, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
import placeholderSVG from "../items/placeholder.svg"; import placeholderSVG from "../items/placeholder.svg";
import { AppContext, ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient";
interface Props { interface Props {
ctx: HookContext ctx: HookContext
@ -31,6 +32,7 @@ export default function MemberSidebar(props: { channel?: Channels.Channel }) {
} }
export function GroupMemberSidebar({ channel, ctx }: Props & { channel: Channels.GroupChannel }) { export function GroupMemberSidebar({ channel, ctx }: Props & { channel: Channels.GroupChannel }) {
const { openScreen } = useIntermediate();
const users = useUsers(undefined, ctx); const users = useUsers(undefined, ctx);
let members = channel.recipients let members = channel.recipients
.map(x => users.find(y => y?._id === x)) .map(x => users.find(y => y?._id === x))
@ -112,13 +114,11 @@ export function GroupMemberSidebar({ channel, ctx }: Props & { channel: Channels
{members.map( {members.map(
user => user =>
user && ( user && (
// <LinkProfile user_id={user._id}> <UserButton
<UserButton key={user._id}
key={user._id} user={user}
user={user} context={channel}
context={channel} onClick={() => openScreen({ id: 'profile', user_id: user._id })} />
/>
// </LinkProfile>
) )
)} )}
</GenericSidebarList> </GenericSidebarList>

View file

@ -98,7 +98,7 @@ export default function Intermediate(props: Props) {
const navigate = (path: string) => history.push(path); const navigate = (path: string) => history.push(path);
const subs = [ const subs = [
internalSubscribe("Intermediate", "open_profile", openProfile), internalSubscribe("Intermediate", "openProfile", openProfile),
internalSubscribe("Intermediate", "navigate", navigate) internalSubscribe("Intermediate", "navigate", navigate)
] ]