refactor: finished tailwind

This commit is contained in:
Tristan Yang
2023-02-08 15:03:30 +08:00
parent cb08a443f3
commit ffd68f2c06
55 changed files with 260 additions and 1313 deletions
+1 -1
View File
@@ -96,7 +96,7 @@ const Commands: FC<Props> = ({ context = "user", contextId = 0, mid = 0, toggleE
<>
<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')}>
className={clsx(`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 group-hover:visible`, tippyVisible && '!visible')}>
<Tippy
onShow={handleTippyVisible.bind(null, true)}
onHide={handleTippyVisible.bind(null, false)}
@@ -1,5 +1,4 @@
import { FC, ReactElement, useEffect, useState } from "react";
import StyledMsg from "./styled";
import renderContent from "./renderContent";
import Avatar from "../Avatar";
import useFavMessage from "../../hook/useFavMessage";
@@ -18,22 +17,22 @@ const FavoredMessage: FC<Props> = ({ id = "" }) => {
const favorite_mids = messages.map(({ from_mid }) => +from_mid) || [];
setMsgs(
<div data-favorite-mids={favorite_mids.join(",")} className="favorite flex flex-col rounded-md bg-slate-200">
<div data-favorite-mids={favorite_mids.join(",")} className="favorite flex flex-col rounded-md bg-slate-50 dark:bg-slate-800">
<div className="list">
{messages.map((msg, idx) => {
const { user = {}, download, content, content_type, properties, thumbnail } = msg;
return (
<StyledMsg className="archive" key={idx}>
<div className="w-full relative flex items-start gap-3 px-2 py-1 my-2 rounded-lg dark:hover:bg-gray-800" key={idx}>
{user && (
<div className="avatar">
<div className="">
<Avatar width={40} height={40} src={user.avatar} name={user.name} />
</div>
)}
<div className="details">
<div className="up">
<span className="name">{user?.name || "Deleted User"}</span>
<div className="w-full flex flex-col gap-2 text-sm">
<div className="flex items-center gap-2 font-semibold">
<span className="text-gray-600 dark:text-gray-400">{user?.name || "Deleted User"}</span>
</div>
<div className="down">
<div className="select-text text-gray-800 break-all whitespace-pre-wrap dark:text-white">
{renderContent({
download,
content,
@@ -43,7 +42,7 @@ const FavoredMessage: FC<Props> = ({ id = "" }) => {
})}
</div>
</div>
</StyledMsg>
</div>
);
})}
</div>
@@ -26,7 +26,7 @@ const ForwardedMessage: FC<Props> = ({ context, to, from_uid, id }) => {
const forward_mids = messages.map(({ from_mid }) => from_mid) || [];
// console.log("fff", messages);
setForwards(
<div data-forwarded-mids={forward_mids.join(",")} className="flex flex-col rounded-lg bg-gray-100">
<div data-forwarded-mids={forward_mids.join(",")} className="flex flex-col rounded-lg bg-gray-100 dark:bg-gray-900">
<h4 className="p-2 pb-0 flex items-center gap-1 text-gray-500 text-xs">
<IconForward className="w-4 h-4 fill-gray-500" />
{t("action.forward")}
@@ -35,17 +35,17 @@ const ForwardedMessage: FC<Props> = ({ context, to, from_uid, id }) => {
{messages.map((msg, idx) => {
const { user = {}, download, content, content_type, properties, thumbnail } = msg;
return (
<StyledMsg className="archive" key={idx}>
<div className="w-full relative flex items-start gap-4 px-2 py-1 my-2 rounded-lg" key={idx}>
{user && (
<div className="avatar">
<div >
<Avatar width={24} height={24} src={user.avatar} name={user.name} />
</div>
)}
<div className="details">
<div className="up">
<span className="name">{user?.name || "Deleted User"}</span>
<div className="w-full flex flex-col">
<div className="flex items-center gap-2 font-semibold">
<span className="text-gray-500 text-sm">{user?.name || "Deleted User"}</span>
</div>
<div className="down">
<div className="select-text text-gray-500 text-sm break-all whitespace-pre-wrap dark:text-white">
{renderContent({
download,
context,
@@ -58,7 +58,7 @@ const ForwardedMessage: FC<Props> = ({ context, to, from_uid, id }) => {
})}
</div>
</div>
</StyledMsg>
</div>
);
})}
</div>
@@ -1,9 +1,7 @@
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";
interface Props {
@@ -16,20 +14,19 @@ const PreviewMessage: FC<Props> = ({ mid = 0, context }) => {
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 { from_uid = 0, content_type, content, thumbnail = "", properties } = msg;
const { name, avatar } = usersData[from_uid] ?? {};
const pinMsg = context == "pin";
return (
<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">
<div className={clsx(`w-full relative flex items-start gap-3 p-2 my-2 rounded-lg`, pinMsg && "max-h-64 overflow-auto overflow-x-hidden border border-solid border-gray-200 dark:border-gray-400")}>
<div>
<Avatar width={40} height={40} src={avatar} name={name} />
</div>
<div className="details">
<div className="up">
<span className="name">{name}</span>
<i className="time">{dayjs(created_at).format("YYYY-MM-DD h:mm:ss A")}</i>
<div className="w-full flex flex-col items-start">
<div className="flex items-center gap-2 font-semibold">
<span className="text-gray-500 text-sm">{name}</span>
</div>
<div className={`down`}>
<div className={`select-text text-gray-600 text-sm break-all whitespace-pre-wrap dark:text-white`}>
{renderContent({
content_type,
content,
@@ -39,7 +36,7 @@ const PreviewMessage: FC<Props> = ({ mid = 0, context }) => {
})}
</div>
</div>
</StyledWrapper>
</div>
);
};
+5 -5
View File
@@ -14,14 +14,14 @@ const renderContent = (data: MessagePayload) => {
switch (content_type) {
case ContentTypes.text:
res = (
<span className="text-ellipsis overflow-hidden break-words break-all text-gray-800">
<span className="text-ellipsis overflow-hidden break-words break-all text-gray-800 dark:text-gray-100">
<LinkifyText text={content} url={false} mentionTextOnly={true} mentionPopOver={false} />
</span>
);
break;
case ContentTypes.markdown:
res = (
<div className="max-h-[152px] overflow-hidden">
<div className="max-h-[152px] overflow-hidden dark:text-gray-100">
<MarkdownRender content={content} />
</div>
);
@@ -36,7 +36,7 @@ const renderContent = (data: MessagePayload) => {
res = (
<>
{icon}
<span className="ml-1 text-[10px] text-gray-500">{name}</span>
<span className="ml-1 text-[10px] text-gray-500 dark:text-gray-100">{name}</span>
</>
);
}
@@ -77,7 +77,7 @@ const Reply: FC<ReplyProps> = ({ mid, interactive = true }) => {
<div
key={mid}
data-mid={mid}
className={`flex items-start p-2 bg-gray-100 rounded-lg gap-2 mb-1 ${interactive ? "cursor-pointer" : "!bg-transparent"}`}
className={`flex items-start p-2 bg-gray-100 dark:bg-gray-900 rounded-lg gap-2 mb-1 ${interactive ? "cursor-pointer" : "!bg-transparent"}`}
onClick={interactive ? handleClick : undefined}
>
<div className="flex items-center gap-1 whitespace-nowrap">
@@ -90,7 +90,7 @@ const Reply: FC<ReplyProps> = ({ mid, interactive = true }) => {
/>
<span className="text-sm text-primary-500">{currUser.name}</span>
</div>
<div className="text-sm flex items-center text-gray-400 overflow-hidden">{renderContent(data)}</div>
<div className="text-sm flex items-center overflow-hidden">{renderContent(data)}</div>
</div>
);
};
+18 -12
View File
@@ -1,13 +1,13 @@
import React, { useRef, useState, useEffect, FC } from "react";
import dayjs from "dayjs";
import Tippy from "@tippyjs/react";
import clsx from "clsx";
import useInView from "./useInView";
import Tippy from "@tippyjs/react";
import Reaction from "./Reaction";
import Reply from "./Reply";
import Profile from "../Profile";
import Avatar from "../Avatar";
import StyledWrapper from "./styled";
import Commands from "./Commands";
import EditMessage from "./EditMessage";
import renderContent from "./renderContent";
@@ -91,13 +91,16 @@ const Message: FC<IProps> = ({
const _key = properties?.local_id || mid;
const showExpire = (expires_in ?? 0) > 0;
return (
<StyledWrapper
<div
key={_key}
onContextMenu={readOnly ? undefined : handleContextMenuEvent}
data-msg-mid={mid}
ref={inviewRef}
className={`message dark:hover:!bg-gray-800 ${readOnly ? "readonly" : ""} ${showExpire ? "auto_delete" : ""} ${pinInfo ? "pinned" : ""} ${contextMenuVisible ? "contextVisible" : ""
} `}
className={clsx(`group w-full relative flex items-start gap-4 px-2 py-1 my-2 rounded-lg dark:hover:bg-gray-800 hover:bg-gray-50`,
readOnly && "hover:bg-transparent",
showExpire && "bg-red-200",
pinInfo && "bg-cyan-50 dark:bg-cyan-800 pt-7"
)}
>
<Tippy
key={_key}
@@ -108,7 +111,7 @@ const Message: FC<IProps> = ({
trigger="click"
content={<Profile uid={fromUid || 0} type="card" cid={context == "user" ? 0 : contextId} />}
>
<div className="avatar" data-uid={fromUid} ref={avatarRef}>
<div className="cursor-pointer" data-uid={fromUid} ref={avatarRef}>
<Avatar width={40} height={40} src={currUser?.avatar} name={currUser?.name} />
</div>
</Tippy>
@@ -121,26 +124,29 @@ const Message: FC<IProps> = ({
hide={hideContextMenu}
>
<div
className="details"
className={clsx("w-full flex flex-col gap-2", pinInfo && "relative")}
data-pin-tip={`pinned by ${pinInfo?.created_by ? usersData[pinInfo.created_by]?.name : ""
}`}
>
<div className="up">
<span className="name">{currUser?.name || "Deleted User"}</span>
{pinInfo && <span className="absolute left-0 -top-1 -translate-y-full text-xs text-gray-400">
{`pinned by ${pinInfo.created_by ? usersData[pinInfo.created_by]?.name : ""}`}
</span>}
<div className="flex items-center gap-2 font-semibold">
<span className="text-primary-500 text-sm">{currUser?.name || "Deleted User"}</span>
<Tooltip
delay={200}
disabled={!timePrefix || readOnly}
placement="top"
tip={dayjsTime.format("YYYY-MM-DD h:mm:ss A")}
>
<time className="time">
<time className="text-gray-400 text-xs">
{timePrefix
? `${timePrefix} ${dayjsTime.format("h:mm A")}`
: dayjsTime.format("YYYY-MM-DD h:mm:ss A")}
</time>
</Tooltip>
</div>
<div className={`down dark:!text-white ${sending ? "sending" : ""}`}>
<div className={`select-text text-gray-800 text-sm break-all whitespace-pre-wrap dark:!text-white ${sending ? "opacity-90" : ""}`}>
{reply_mid && <Reply key={reply_mid} mid={reply_mid} />}
{edit ? (
<EditMessage mid={mid} cancelEdit={toggleEditMessage} />
@@ -180,7 +186,7 @@ const Message: FC<IProps> = ({
toggleEditMessage={toggleEditMessage}
/>
)}
</StyledWrapper>
</div>
);
};
export default React.memo(Message, (prevs, nexts) => {
@@ -39,7 +39,7 @@ const renderContent = ({
<>
<LinkifyText text={content} cid={to} />
{edited && (
<span className="edited" title={dayjs(+edited).format("YYYY-MM-DD h:mm:ss A")}>
<span className="ml-1 text-gray-500 text-[10px]" title={dayjs(+edited).format("YYYY-MM-DD h:mm:ss A")}>
({i18n.t("edited", { ns: "chat" })})
</span>
)}
-129
View File
@@ -1,129 +0,0 @@
import styled from "styled-components";
const StyledMsg = styled.div`
width: 100%;
position: relative;
display: flex;
align-items: flex-start;
gap: 16px;
padding: 4px 8px;
margin: 8px 0;
border-radius: 8px;
&[data-highlight="true"] {
background: #f5f6f7;
}
&.auto_delete {
background: #f1d1ca50;
}
&.pinned {
background: #ecfdff;
}
&:hover,
&.contextVisible,
&.preview {
background: #f5f6f7;
.cmds {
visibility: visible;
}
}
&.readonly:hover {
background: none;
}
> .avatar {
flex-shrink: 0;
cursor: pointer;
width: 40px;
height: 40px;
img {
object-fit: cover;
width: 100%;
height: 100%;
border-radius: 50%;
}
}
> .details {
width: 100%;
display: flex;
flex-direction: column;
gap: 8px;
.up {
display: flex;
align-items: center;
gap: 8px;
font-weight: 500;
.name {
color: #06b6d4;
font-style: normal;
font-size: 14px;
line-height: 20px;
}
.time {
color: #bfbfbf;
font-size: 12px;
line-height: 18px;
}
}
.down {
user-select: text;
color: #374151;
font-weight: normal;
font-size: 14px;
line-height: 20px;
word-break: break-all;
white-space: pre-wrap;
.edited {
margin-left: 5px;
color: #999;
font-size: 10px;
}
&.sending {
opacity: 0.9;
}
> .link {
text-decoration: none;
border-radius: 2px;
/* background-color: #f5feff; */
padding: 2px;
color: #1fe1f9;
}
/* 下载图标颜色 */
.download_icon.gray{
path{
fill: #616161;
}
}
}
}
&.archive {
gap: 8px;
> .details {
gap: 0;
.up .name {
font-weight: 600;
color: #475467;
}
.down {
color: #475467;
}
}
}
&.pinned {
padding-top: 26px;
> .details {
position: relative;
&:before {
position: absolute;
left: 0;
top: -4px;
transform: translateY(-100%);
content: attr(data-pin-tip);
font-weight: 400;
font-size: 12px;
line-height: 18px;
color: #98a2b3;
}
}
}
`;
export default StyledMsg;