feat: darkmode draft version

This commit is contained in:
Tristan Yang
2023-02-06 07:35:31 +08:00
parent b4c5d5cb86
commit 07ddfbf12b
111 changed files with 885 additions and 2102 deletions
+23 -53
View File
@@ -1,6 +1,5 @@
import { useState, useRef, FC } from "react";
import { useDispatch } from "react-redux";
import styled from "styled-components";
import Tippy from "@tippyjs/react";
import { hideAll } from "tippy.js";
import toast from "react-hot-toast";
@@ -21,47 +20,7 @@ import IconDelete from "../../../assets/icons/delete.svg";
import moreIcon from "../../../assets/icons/more.svg?url";
import useMessageOperation from "./useMessageOperation";
import { useTranslation } from "react-i18next";
const StyledCmds = styled.ul`
z-index: 999;
position: absolute;
right: 10px;
top: 0;
transform: translateY(-50%);
display: flex;
align-items: center;
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 6px;
background-color: #fff;
visibility: hidden;
&.visible {
visibility: visible;
}
.cmd {
display: flex;
cursor: pointer;
padding: 4px;
&:hover {
background-color: #f3f4f6;
}
img,
svg {
width: 24px;
height: 24px;
}
&.fav {
svg path {
fill: #667085;
}
}
}
> .picker {
position: absolute;
left: -10px;
top: 0;
transform: translateX(-100%);
}
`;
import clsx from "clsx";
type Props = {
context: "user" | "channel";
contextId: number;
@@ -124,9 +83,20 @@ const Commands: FC<Props> = ({ context = "user", contextId = 0, mid = 0, toggleE
}
};
// const StyledCmds = styled.ul`
// > .picker {
// position: absolute;
// left: -10px;
// top: 0;
// transform: translateX(-100%);
// }
// `;
return (
<>
<StyledCmds ref={cmdsRef} className={`cmds ${tippyVisible ? "visible" : ""}`}>
<ul
ref={cmdsRef}
className={clsx(`cmds bg-white dark:bg-gray-900 rounded-md z-[999] absolute right-2.5 top-0 -translate-y-1/2 flex items-center border border-solid border-black/10 invisible`, tippyVisible && '!visible')}>
<Tippy
onShow={handleTippyVisible.bind(null, true)}
onHide={handleTippyVisible.bind(null, false)}
@@ -135,29 +105,29 @@ const Commands: FC<Props> = ({ context = "user", contextId = 0, mid = 0, toggleE
trigger="click"
content={<ReactionPicker mid={mid} hidePicker={hideAll} />}
>
<li className="cmd">
<li className="flex cursor-pointer p-1 hover:bg-[#f3f4f6] dark:hover:bg-gray-800">
<Tooltip placement="top" tip={t("action.add_reaction")}>
<img src={reactIcon} className="toggler" alt="icon emoji" />
<img src={reactIcon} className="toggler w-6 h-6" alt="icon emoji" />
</Tooltip>
</li>
</Tippy>
{canEdit && (
<li className="cmd" onClick={toggleEditMessage}>
<li className="flex cursor-pointer p-1 hover:bg-[#f3f4f6] dark:hover:bg-gray-800" onClick={toggleEditMessage}>
<Tooltip placement="top" tip={t("action.edit")}>
<img src={editIcon} alt="icon edit" />
<img src={editIcon} className="w-6 h-6" alt="icon edit" />
</Tooltip>
</li>
)}
{canReply && (
<li className="cmd" onClick={handleReply}>
<li className="flex cursor-pointer p-1 hover:bg-[#f3f4f6] dark:hover:bg-gray-800" onClick={handleReply}>
<Tooltip placement="top" tip={t("action.reply")}>
<img src={replyIcon} alt="icon reply" />
<img src={replyIcon} className="w-6 h-6" alt="icon reply" />
</Tooltip>
</li>
)}
<li className="cmd fav" onClick={handleAddFav}>
<li className="flex cursor-pointer p-1 hover:bg-[#f3f4f6] dark:hover:bg-gray-800" onClick={handleAddFav}>
<Tooltip placement="top" tip={t("action.add_to_fav")}>
<IconBookmark />
<IconBookmark className="fill-[#667085] w-6 h-6" />
</Tooltip>
</li>
<Tippy
@@ -196,13 +166,13 @@ const Commands: FC<Props> = ({ context = "user", contextId = 0, mid = 0, toggleE
/>
}
>
<li className="cmd">
<li className="flex cursor-pointer p-1 hover:bg-[#f3f4f6] dark:hover:bg-gray-800">
<Tooltip placement="top" tip={t("more")}>
<img src={moreIcon} alt="icon more" />
</Tooltip>
</li>
</Tippy>
</StyledCmds>
</ul>
{PinModal}
{ForwardModal}
{DeleteModal}
+2 -11
View File
@@ -1,17 +1,8 @@
// import { FC, ReactNode } from "react";
import Tippy from "@tippyjs/react";
import styled from "styled-components";
import Profile from "../Profile";
import { useAppSelector } from "../../../app/store";
const Styled = styled.span`
padding: 0 2px;
color: #1fe1f9;
&.clickable {
cursor: pointer;
}
`;
interface Props {
uid: number;
popover?: boolean;
@@ -24,7 +15,7 @@ const Mention = ({ uid, popover = true, cid, textOnly = false }: Props) => {
const user = usersData[uid];
if (!user) return null;
if (textOnly) return <>{`@${user.name}`}</>;
if (!popover) return <Styled>{`@${user.name}`}</Styled>;
if (!popover) return <span className="px-0.5 text-primary-400">{`@${user.name}`}</span>;
return (
<Tippy
interactive
@@ -32,7 +23,7 @@ const Mention = ({ uid, popover = true, cid, textOnly = false }: Props) => {
trigger="click"
content={<Profile uid={uid} type="card" cid={cid} />}
>
<Styled className="clickable">{`@${user.name}`}</Styled>
<span className="px-0.5 text-primary-400 cursor-pointer">{`@${user.name}`}</span>
</Tippy>
);
};
@@ -1,6 +1,5 @@
import { FC } from "react";
import { useEffect } from "react";
import styled from "styled-components";
import toast from "react-hot-toast";
import usePinMessage from "../../hook/usePinMessage";
import StyledModal from "../styled/Modal";
@@ -9,20 +8,6 @@ import Modal from "../Modal";
import PreviewMessage from "./PreviewMessage";
import { useTranslation } from "react-i18next";
const StyledPinModal = styled(StyledModal)`
min-width: 406px;
.title,
.desc {
text-align: left;
}
.preview {
border: 1px solid #f2f4f7;
max-height: 256px;
overflow: auto;
background: none;
overflow-x: hidden;
}
`;
interface Props {
closeModal: () => void;
@@ -40,7 +25,7 @@ const PinMessageModal: FC<Props> = ({ closeModal, mid = 0, gid = 0 }) => {
useEffect(() => {
if (isSuccess) {
closeModal();
toast.success("Pin Message Successfully");
toast.success(t("tip.pin"));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSuccess]);
@@ -48,8 +33,8 @@ const PinMessageModal: FC<Props> = ({ closeModal, mid = 0, gid = 0 }) => {
if (!mid) return null;
return (
<Modal>
<StyledPinModal
// className="animate__animated animate__fadeInDown animate__faster"
<StyledModal
className="min-w-[406px]"
buttons={
<>
<Button onClick={closeModal} className="cancel">
@@ -63,8 +48,8 @@ const PinMessageModal: FC<Props> = ({ closeModal, mid = 0, gid = 0 }) => {
title={t("action.pin")}
description={`Do you want to pin this message to #${channel?.name}`}
>
<PreviewMessage mid={mid} />
</StyledPinModal>
<PreviewMessage mid={mid} context="pin" />
</StyledModal>
</Modal>
);
};
@@ -1,23 +1,26 @@
import { FC } from "react";
import clsx from "clsx";
import dayjs from "dayjs";
import renderContent from "./renderContent";
import Avatar from "../Avatar";
import StyledWrapper from "./styled";
import { useAppSelector } from "../../../app/store";
import { FC } from "react";
interface Props {
mid?: number;
context?: "forward" | "pin"
}
const PreviewMessage: FC<Props> = ({ mid = 0 }) => {
const PreviewMessage: FC<Props> = ({ mid = 0, context }) => {
const { msg, usersData } = useAppSelector((store) => {
return { msg: store.message[mid], usersData: store.users.byId };
});
if (!msg) return null;
const { from_uid = 0, created_at, content_type, content, thumbnail = "", properties } = msg;
const { name, avatar } = usersData[from_uid] ?? {};
const pinMsg = context == "pin";
return (
<StyledWrapper className={`preview`}>
<StyledWrapper className={clsx(`preview`, pinMsg && "max-h-64 !bg-transparent overflow-auto overflow-x-hidden border border-solid border-gray-200 dark:border-gray-400")}>
<div className="avatar">
<Avatar width={40} height={40} src={avatar} name={name} />
</div>
+4 -4
View File
@@ -96,7 +96,7 @@ const Message: FC<IProps> = ({
onContextMenu={readOnly ? undefined : handleContextMenuEvent}
data-msg-mid={mid}
ref={inviewRef}
className={`message ${readOnly ? "readonly" : ""} ${showExpire ? "auto_delete" : ""} ${pinInfo ? "pinned" : ""} ${contextMenuVisible ? "contextVisible" : ""
className={`message dark:hover:!bg-gray-800 ${readOnly ? "readonly" : ""} ${showExpire ? "auto_delete" : ""} ${pinInfo ? "pinned" : ""} ${contextMenuVisible ? "contextVisible" : ""
} `}
>
<Tippy
@@ -133,14 +133,14 @@ const Message: FC<IProps> = ({
placement="top"
tip={dayjsTime.format("YYYY-MM-DD h:mm:ss A")}
>
<i className="time">
<time className="time">
{timePrefix
? `${timePrefix} ${dayjsTime.format("h:mm A")}`
: dayjsTime.format("YYYY-MM-DD h:mm:ss A")}
</i>
</time>
</Tooltip>
</div>
<div className={`down ${sending ? "sending" : ""}`}>
<div className={`down dark:!text-white ${sending ? "sending" : ""}`}>
{reply_mid && <Reply key={reply_mid} mid={reply_mid} />}
{edit ? (
<EditMessage mid={mid} cancelEdit={toggleEditMessage} />