mirror of
https://github.com/wassname/Open-Assistant.git
synced 2026-07-23 12:40:42 +08:00
Hide message reaction count when user not reacted yet (#1303)
close #1252 Also add a copy message link feature
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"copy_message_id": "Copy message ID",
|
||||
"copy_message_link": "Copy message link",
|
||||
"label_action": "Label",
|
||||
"label_title": "Label",
|
||||
"message_deleted": "Message deleted",
|
||||
|
||||
@@ -8,8 +8,20 @@ export default {
|
||||
component: MessageEmojiButton,
|
||||
};
|
||||
|
||||
const Template = ({ emoji, count, checked }: { emoji: string; count: number; checked?: boolean }) => {
|
||||
return <MessageEmojiButton emoji={{ name: emoji, count }} checked={checked} onClick={undefined} />;
|
||||
const Template = ({
|
||||
emoji,
|
||||
count,
|
||||
checked,
|
||||
showCount,
|
||||
}: {
|
||||
emoji: string;
|
||||
count: number;
|
||||
checked?: boolean;
|
||||
showCount: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<MessageEmojiButton emoji={{ name: emoji, count }} checked={checked} onClick={undefined} showCount={showCount} />
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
@@ -17,6 +29,7 @@ Default.args = {
|
||||
emoji: "+1",
|
||||
count: 7,
|
||||
checked: false,
|
||||
showCount: true,
|
||||
};
|
||||
|
||||
export const BigNumber = Template.bind({});
|
||||
@@ -24,6 +37,7 @@ BigNumber.args = {
|
||||
emoji: "+1",
|
||||
count: 999,
|
||||
checked: false,
|
||||
showCount: true,
|
||||
};
|
||||
|
||||
export const Checked = Template.bind({});
|
||||
@@ -31,4 +45,5 @@ Checked.args = {
|
||||
emoji: "+1",
|
||||
count: 2,
|
||||
checked: true,
|
||||
showCount: true,
|
||||
};
|
||||
|
||||
@@ -6,9 +6,10 @@ interface MessageEmojiButtonProps {
|
||||
emoji: MessageEmoji;
|
||||
checked?: boolean;
|
||||
onClick: () => void;
|
||||
showCount: boolean;
|
||||
}
|
||||
|
||||
export const MessageEmojiButton = ({ emoji, checked, onClick }: MessageEmojiButtonProps) => {
|
||||
export const MessageEmojiButton = ({ emoji, checked, onClick, showCount }: MessageEmojiButtonProps) => {
|
||||
const EmojiIcon = emojiIcons.get(emoji.name);
|
||||
if (!EmojiIcon) return <></>;
|
||||
return (
|
||||
@@ -22,7 +23,7 @@ export const MessageEmojiButton = ({ emoji, checked, onClick }: MessageEmojiButt
|
||||
padding="0"
|
||||
>
|
||||
<EmojiIcon style={{ height: "1em" }} />
|
||||
{emoji.count > 0 && <span style={{ marginInlineEnd: "0.25em" }}>{emoji.count}</span>}
|
||||
{emoji.count > 0 && showCount && <span style={{ marginInlineEnd: "0.25em" }}>{emoji.count}</span>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,14 +15,14 @@ import {
|
||||
useToast,
|
||||
} from "@chakra-ui/react";
|
||||
import { boolean } from "boolean";
|
||||
import { ClipboardList, Copy, Flag, MessageSquare, MoreHorizontal, Slash, Trash, User } from "lucide-react";
|
||||
import { ClipboardList, Copy, Flag, Link, MessageSquare, MoreHorizontal, Slash, Trash, User } from "lucide-react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { LabelMessagePopup } from "src/components/Messages/LabelPopup";
|
||||
import { MessageEmojiButton } from "src/components/Messages/MessageEmojiButton";
|
||||
import { ReportPopup } from "src/components/Messages/ReportPopup";
|
||||
import { useHasRole } from "src/hooks/auth/useHasRole";
|
||||
import { del, post, put } from "src/lib/api";
|
||||
import { colors } from "src/styles/Theme/colors";
|
||||
import { Message, MessageEmojis } from "src/types/Conversation";
|
||||
@@ -116,6 +116,7 @@ export function MessageTableEntry({ message, enabled, highlight }: MessageTableE
|
||||
key={emoji}
|
||||
emoji={{ name: emoji, count }}
|
||||
checked={emojiState.user_emojis.includes(emoji)}
|
||||
showCount={emojiState.user_emojis.filter((emoji) => emoji === "+1" || emoji === "-1").length > 0}
|
||||
onClick={() => react(emoji, !emojiState.user_emojis.includes(emoji))}
|
||||
/>
|
||||
);
|
||||
@@ -170,12 +171,12 @@ const MessageActions = ({
|
||||
}) => {
|
||||
const toast = useToast();
|
||||
const { t } = useTranslation(["message", "common"]);
|
||||
const id = message.id;
|
||||
const displayId = id.slice(0, CHAR_COUNT) + "..." + id.slice(-CHAR_COUNT);
|
||||
const { trigger: deleteMessage } = useSWRMutation(`/api/admin/delete_message/${message.id}`, del);
|
||||
const { id } = message;
|
||||
const { trigger: deleteMessage } = useSWRMutation(`/api/admin/delete_message/${id}`, del);
|
||||
|
||||
const { trigger: stopTree } = useSWRMutation(`/api/admin/stop_tree/${message.id}`, put, {
|
||||
const { trigger: stopTree } = useSWRMutation(`/api/admin/stop_tree/${id}`, put, {
|
||||
onSuccess: () => {
|
||||
const displayId = id.slice(0, CHAR_COUNT) + "..." + id.slice(-CHAR_COUNT);
|
||||
toast({
|
||||
title: t("common:success"),
|
||||
description: t("tree_stopped", { id: displayId }),
|
||||
@@ -186,9 +187,6 @@ const MessageActions = ({
|
||||
},
|
||||
});
|
||||
|
||||
const { data: session } = useSession();
|
||||
const isAdmin = session?.user?.role === "admin";
|
||||
|
||||
const handleDelete = async () => {
|
||||
await deleteMessage();
|
||||
mutate((key) => typeof key === "string" && key.startsWith("/api/messages"), undefined, { revalidate: true });
|
||||
@@ -198,8 +196,10 @@ const MessageActions = ({
|
||||
stopTree();
|
||||
};
|
||||
|
||||
const handleCopyId = () => {
|
||||
navigator.clipboard.writeText(message.id);
|
||||
const handleCopy = (text: string) => {
|
||||
navigator.clipboard.writeText(text);
|
||||
const displayId = text.slice(0, CHAR_COUNT) + "..." + text.slice(-CHAR_COUNT);
|
||||
|
||||
toast({
|
||||
title: t("common:copied"),
|
||||
description: displayId,
|
||||
@@ -209,6 +209,8 @@ const MessageActions = ({
|
||||
});
|
||||
};
|
||||
|
||||
const isAdmin = useHasRole("admin");
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
<MenuButton>
|
||||
@@ -230,13 +232,20 @@ const MessageActions = ({
|
||||
{t("report_action")}
|
||||
</MenuItem>
|
||||
<MenuDivider />
|
||||
<MenuItem as="a" href={`/messages/${message.id}`} target="_blank" icon={<MessageSquare />}>
|
||||
<MenuItem as="a" href={`/messages/${id}`} target="_blank" icon={<MessageSquare />}>
|
||||
{t("open_new_tab_action")}
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
onClick={() => handleCopy(`${window.location.protocol}://${window.location.host}/messages/${id}`)}
|
||||
icon={<Link />}
|
||||
>
|
||||
{t("copy_message_link")}
|
||||
</MenuItem>
|
||||
{!!isAdmin && (
|
||||
<>
|
||||
<MenuDivider />
|
||||
<MenuItem onClick={handleCopyId} icon={<Copy />}>
|
||||
<MenuItem onClick={() => handleCopy(id)} icon={<Copy />}>
|
||||
{t("copy_message_id")}
|
||||
</MenuItem>
|
||||
<MenuItem as="a" href={`/admin/manage_user/${message.user_id}`} target="_blank" icon={<User />}>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { useSession } from "next-auth/react";
|
||||
import { Role } from "src/components/RoleSelect";
|
||||
|
||||
export const useHasRole = (role: Role) => {
|
||||
const { data: session } = useSession();
|
||||
|
||||
return session?.user?.role === role;
|
||||
};
|
||||
@@ -59,7 +59,7 @@ export const getServerSideProps: GetServerSideProps<{ id: string }, { id: string
|
||||
props: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: params!.id,
|
||||
...(await serverSideTranslations(locale, ["common", "message", "labelling"])),
|
||||
...(await serverSideTranslations(locale, ["common", "message", "labelling", "side_menu"])),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user