Skip to content

Commit

Permalink
Hide message reaction count when user not reacted yet (#1303)
Browse files Browse the repository at this point in the history
close #1252
Also add a copy message link feature
  • Loading branch information
notmd committed Feb 8, 2023
1 parent ab77935 commit 7175ce3
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 18 deletions.
1 change: 1 addition & 0 deletions website/public/locales/en/message.json
@@ -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",
Expand Down
19 changes: 17 additions & 2 deletions website/src/components/Messages/MessageEmojiButton.stories.tsx
Expand Up @@ -8,27 +8,42 @@ 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({});
Default.args = {
emoji: "+1",
count: 7,
checked: false,
showCount: true,
};

export const BigNumber = Template.bind({});
BigNumber.args = {
emoji: "+1",
count: 999,
checked: false,
showCount: true,
};

export const Checked = Template.bind({});
Checked.args = {
emoji: "+1",
count: 2,
checked: true,
showCount: true,
};
5 changes: 3 additions & 2 deletions website/src/components/Messages/MessageEmojiButton.tsx
Expand Up @@ -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 (
Expand All @@ -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>
);
};
35 changes: 22 additions & 13 deletions website/src/components/Messages/MessageTableEntry.tsx
Expand Up @@ -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";
Expand Down Expand Up @@ -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))}
/>
);
Expand Down Expand Up @@ -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 }),
Expand All @@ -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 });
Expand All @@ -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,
Expand All @@ -209,6 +209,8 @@ const MessageActions = ({
});
};

const isAdmin = useHasRole("admin");

return (
<Menu>
<MenuButton>
Expand All @@ -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 />}>
Expand Down
8 changes: 8 additions & 0 deletions website/src/hooks/auth/useHasRole.ts
@@ -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;
};
2 changes: 1 addition & 1 deletion website/src/pages/messages/[id]/index.tsx
Expand Up @@ -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"])),
},
});

Expand Down

0 comments on commit 7175ce3

Please sign in to comment.