Hide message reaction count when user not reacted yet (#1303)

close #1252
Also add a copy message link feature
This commit is contained in:
notmd
2023-02-08 15:28:37 +09:00
committed by GitHub
parent ab779352f0
commit 7175ce364c
6 changed files with 52 additions and 18 deletions
+1
View File
@@ -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 />}>
+8
View File
@@ -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;
};
+1 -1
View File
@@ -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"])),
},
});