Skip to content

Commit c0fb0e2

Browse files
committed
feat: add editingMessageId prop to MessageRendererProvider
1 parent bc1cf12 commit c0fb0e2

File tree

5 files changed

+40
-194
lines changed

5 files changed

+40
-194
lines changed

src/Message/variants/EditMessageInput.tsx

Lines changed: 13 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,8 @@
1-
import type {
2-
APIMessageInteraction,
3-
APIRole,
4-
APIUser,
5-
Snowflake,
6-
} from "discord-api-types/v10";
7-
import { MessageType } from "discord-api-types/v10";
8-
import Moment from "moment";
9-
import React, { memo, useMemo, useRef } from "react";
10-
import ChatTag from "../../ChatTag";
11-
import Content from "../../Content";
12-
import Tooltip from "../../Tooltip";
1+
import React from "react";
132
import { useConfig } from "../../core/ConfigContext";
143
import type { ChatMessage } from "../../types";
15-
import type { GetAvatarOptions } from "../../utils/getAvatar";
16-
import getAvatar from "../../utils/getAvatar";
17-
import getDisplayName from "../../utils/getDisplayName";
18-
import LargeTimestamp from "../LargeTimestamp";
19-
import MessageAuthor from "../MessageAuthor";
20-
import * as Styles from "../style/message";
21-
22-
interface ReplyInfoProps {
23-
channelId: Snowflake;
24-
referencedMessage: ChatMessage["referenced_message"];
25-
mentioned?: boolean;
26-
interaction: APIMessageInteraction | undefined;
27-
isContextMenuInteraction?: boolean;
28-
}
29-
30-
function getMiniAvatarUrl(user: APIUser) {
31-
const getAvatarSettings: GetAvatarOptions = {
32-
size: 16,
33-
};
34-
35-
return getAvatar(user, getAvatarSettings);
36-
}
37-
38-
const FLAG_CROSSPOST = 1 << 1;
39-
40-
const ReplyInfo = memo((props: ReplyInfoProps) => {
41-
const user = props.interaction
42-
? props.interaction.user
43-
: props.referencedMessage?.author;
44-
45-
const { resolveRole, resolveChannel, resolveMember, avatarUrlOverride } =
46-
useConfig();
47-
const miniUserName = useMemo(() => {
48-
if (!props.interaction && !props.referencedMessage) return null;
49-
50-
if (user === undefined) return null;
51-
52-
if (!resolveChannel) return getDisplayName(user);
53-
54-
const channel = resolveChannel(props.channelId);
55-
if (
56-
!channel ||
57-
!("guild_id" in channel) ||
58-
!channel.guild_id ||
59-
!props.referencedMessage
60-
)
61-
return getDisplayName(user);
62-
63-
const guildMember = resolveMember(
64-
props.referencedMessage.author,
65-
channel.guild_id
66-
);
67-
68-
if (!guildMember) return getDisplayName(user);
69-
70-
return guildMember.nick ?? getDisplayName(guildMember.user as APIUser);
71-
}, [props.referencedMessage, props.interaction, resolveChannel]);
72-
73-
const miniAvatarUrl = useMemo(
74-
() =>
75-
user === undefined
76-
? null
77-
: avatarUrlOverride?.(user) ?? getMiniAvatarUrl(user),
78-
[props.referencedMessage, props.interaction]
79-
);
80-
81-
const miniUserNameColorHex = useMemo(() => {
82-
if (!props.referencedMessage) return undefined;
83-
84-
const channel = resolveChannel(props.referencedMessage.channel_id);
85-
if (!channel || !("guild_id" in channel) || !channel.guild_id)
86-
return undefined;
87-
88-
const guildMember = resolveMember(
89-
props.referencedMessage.author,
90-
channel.guild_id
91-
);
92-
93-
if (!guildMember) return undefined;
94-
95-
const [role] = guildMember.roles
96-
.map((id) => resolveRole(id))
97-
.filter(
98-
(role): role is APIRole =>
99-
role !== null && role !== undefined && role.color !== 0
100-
)
101-
.sort((a, b) => b.position - a.position);
102-
103-
const color = role?.color;
104-
if (!color) return undefined;
105-
106-
return color > 0 ? `#${color.toString(16).padStart(6, "0")}` : undefined;
107-
}, [resolveRole]);
1084

109-
const unknownReply = !props.referencedMessage && !props.interaction;
110-
111-
return (
112-
<Styles.ReplyInfo>
113-
<Styles.ReplySpine />
114-
{unknownReply ? (
115-
<>
116-
<Styles.UnknownReplyIcon
117-
width={12}
118-
height={12}
119-
svg="IconUnknownReply"
120-
/>
121-
<Styles.UnknownReply>
122-
Original message was deleted or is unknown.
123-
</Styles.UnknownReply>
124-
</>
125-
) : (
126-
<Styles.ReplyUser>
127-
{miniAvatarUrl && (
128-
<Styles.MiniUserAvatar src={miniAvatarUrl.stillAvatarUrl} />
129-
)}
130-
{props.referencedMessage && (
131-
<ChatTag
132-
author={props.referencedMessage.author}
133-
crossPost={Boolean(
134-
(props.referencedMessage.flags ?? 0) & FLAG_CROSSPOST
135-
)}
136-
referenceGuild={
137-
props.referencedMessage.message_reference?.guild_id
138-
}
139-
/>
140-
)}
141-
<Styles.MiniUserName style={{ color: miniUserNameColorHex }}>
142-
{props.mentioned && "@"}
143-
{miniUserName}
144-
</Styles.MiniUserName>
145-
</Styles.ReplyUser>
146-
)}
147-
{props.referencedMessage ? (
148-
<Content message={props.referencedMessage} isReplyContent={true} />
149-
) : (
150-
props.interaction && (
151-
<Styles.SlashCommand>
152-
used{" "}
153-
<Styles.SlashCommandText>
154-
{!props.isContextMenuInteraction ? "/" : ""}
155-
{props.interaction.name}
156-
</Styles.SlashCommandText>
157-
</Styles.SlashCommand>
158-
)
159-
)}
160-
</Styles.ReplyInfo>
161-
);
162-
});
163-
164-
ReplyInfo.displayName = "ReplyInfo";
165-
166-
// type Message = Omit<MessageData, "referencedMessage"> & Partial<MessageData>;
5+
import * as Styles from "../style/message";
1676

1687
interface EditMessageInputProps {
1698
// isFirstMessage?: boolean;
@@ -181,24 +20,28 @@ interface EditMessageInputProps {
18120
function EditMessageInput(props: EditMessageInputProps) {
18221
const { handleMessageEditSubmit } = useConfig();
18322

184-
const submitMessageCallback = (content: string) => {
23+
function submitMessageCallback(content: string) {
18524
if (!handleMessageEditSubmit || !content) return;
18625

18726
handleMessageEditSubmit({
18827
...props.message,
18928
content: content,
19029
edited_timestamp: new Date().getMilliseconds().toString(),
19130
});
192-
};
31+
}
32+
33+
function onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
34+
const target = e.target as HTMLInputElement;
35+
36+
if (e.key === "Enter") {
37+
submitMessageCallback(target.value);
38+
}
39+
}
19340

19441
return (
19542
<Styles.MessageEditor
19643
autoCorrect={"false"}
197-
onKeyDown={(e) => {
198-
if (e.key === "Enter") {
199-
submitMessageCallback(e.target.value);
200-
}
201-
}}
44+
onKeyDown={onKeyDown}
20245
defaultValue={props.message.content}
20346
/>
20447
);

src/Message/variants/NormalMessage.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,11 @@ const ReplyInfo = memo((props: ReplyInfoProps) => {
163163

164164
ReplyInfo.displayName = "ReplyInfo";
165165

166-
// type Message = Omit<MessageData, "referencedMessage"> & Partial<MessageData>;
167-
168166
interface MessageProps {
169167
isFirstMessage?: boolean;
170168
message: ChatMessage;
171169
isHovered?: boolean;
172170
noThreadButton?: boolean;
173-
isEditing?: boolean;
174171
isContextMenuInteraction?: boolean;
175172
hideTimestamp?: boolean;
176173
overrides?: {
@@ -183,7 +180,12 @@ function NormalMessage(props: MessageProps) {
183180
props.message.type === MessageType.Reply ||
184181
Boolean(props.message.interaction);
185182

186-
const { currentUser, resolveChannel, EditMessageComponent } = useConfig();
183+
const {
184+
currentUser,
185+
resolveChannel,
186+
editingMessageId,
187+
EditMessageComponent,
188+
} = useConfig();
187189

188190
const channel = resolveChannel(props.message.channel_id);
189191
const guildId =
@@ -235,13 +237,14 @@ function NormalMessage(props: MessageProps) {
235237
<LargeTimestamp timestamp={props.message.timestamp} />
236238
)}
237239
</Styles.MessageHeaderBase>
238-
{EditMessageComponent ? (
240+
{editingMessageId === props.message.id && EditMessageComponent ? (
239241
<EditMessageComponent message={props.message} />
240-
) : null}
241-
{/* <Content
242-
message={props.message}
243-
noThreadButton={props.noThreadButton}
244-
/> */}
242+
) : (
243+
<Content
244+
message={props.message}
245+
noThreadButton={props.noThreadButton}
246+
/>
247+
)}
245248
</Styles.Message>
246249
);
247250

src/core/ConfigContext.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import type {
1010
import type { APIAttachment } from "discord-api-types/v10";
1111
import type { ReactElement } from "react";
1212
import { createContext, useContext } from "react";
13-
import EditMessageInput from "src/Message/variants/EditMessageInput";
1413
import type { Tag } from "../ChatTag/style";
1514
import type { ChatMessage } from "../types";
1615
import type { UserAvatar } from "../utils/getAvatar";
@@ -51,6 +50,7 @@ export type Config<SvgConfig extends PartialSvgConfig> = {
5150
avatarUrlOverride?(user: APIUser): UserAvatar | null;
5251
themeOverrideClassName?: string;
5352
unknownMessageTypeResponse?: MessageTypeResponse;
53+
editingMessageId?: string;
5454

5555
// Click handlers
5656
currentUser(): APIUser | null;
@@ -64,7 +64,7 @@ export type Config<SvgConfig extends PartialSvgConfig> = {
6464
embedImageOnClick?(image: APIEmbedImage): void;
6565
externalLinkOpenRequested?(url: string): void;
6666
handleMessageEditSubmit?(message: ChatMessage): void;
67-
EditMessageComponent?:( (props: { message: ChatMessage }) => JSX.Element);
67+
EditMessageComponent?: (props: { message: ChatMessage }) => JSX.Element;
6868
};
6969

7070
export const ConfigContext = createContext<Config<PartialSvgConfig>>({
@@ -79,7 +79,6 @@ export const ConfigContext = createContext<Config<PartialSvgConfig>>({
7979
still: "",
8080
animated: "",
8181
},
82-
EditMessageComponent: EditMessageInput,
8382
});
8483

8584
export function useConfig() {

src/stories/Normal.stories.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,20 +1008,21 @@ VideoAttachment.args = {
10081008

10091009
export const Editing: StoryFn<typeof MessageGroup> = Template.bind({});
10101010
Editing.args = {
1011+
showButtons: true,
10111012
messages: [
10121013
{
1013-
id: "1101275906716213339",
1014+
id: "1101275906716213331",
10141015
type: 0,
10151016
content:
10161017
"Small update: We needed to roll this back ~~for 24 hours~~ to patch some security issues. It'll be back real soon. Update: we don't want to re-roll it out on a friday afternoon, so thisll be back next week.",
10171018
channel_id: "697138785317814292",
10181019
author: {
1019-
id: "933123872641921044",
1020-
username: "therealjethro",
1021-
global_name: "Jeff",
1022-
avatar: "e4d8c186d8900eed2ace6aed5cefe1c0",
1023-
discriminator: "0",
1024-
public_flags: 4604871,
1020+
id: "132819036282159104",
1021+
username: "mrquine",
1022+
global_name: "Mr. Quine",
1023+
avatar: "3a30ffeeeb354950804d77ded94162d3",
1024+
discriminator: "0001",
1025+
public_flags: 4457220,
10251026
},
10261027
attachments: [],
10271028
embeds: [],
@@ -1057,7 +1058,6 @@ Editing.args = {
10571058
me: false,
10581059
},
10591060
],
1060-
10611061
},
10621062
],
10631063
};

src/stories/Wrapper.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,15 +384,16 @@ const Wrapper: Decorator = (Story) => {
384384
animated: automodAvatarAnimated,
385385
}}
386386
EditMessageComponent={EditMessageInput}
387+
handleMessageEditSubmit={(message) => {
388+
alert(`Edited message: ${message.id}`);
389+
}}
390+
editingMessageId="1101275906716213331"
387391
messageButtons={getButtons}
388392
resolveRole={resolveRole}
389393
resolveChannel={resolveChannel}
390394
resolveMember={resolveMember}
391395
resolveGuild={resolveGuild}
392396
resolveUser={resolveUser}
393-
handleMessageEditSubmit={(message) => {
394-
alert(`Edited message: ${message.id}`);
395-
}}
396397
currentUser={() => resolveUser("132819036282159104")}
397398
seeThreadOnClick={(messageId, thread) =>
398399
alert(`See Thread "${thread.name}" clicked on message ${messageId}`)

0 commit comments

Comments
 (0)