chore: update prettier setting

This commit is contained in:
zerosoul
2022-06-12 15:30:14 +08:00
parent 14b4678d9e
commit 516794d352
209 changed files with 2435 additions and 4588 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
import styled from 'styled-components';
import styled from "styled-components";
const StyledWrapper = styled.div`
display: flex;
display: flex;
`;
export default StyledWrapper;
+2 -8
View File
@@ -96,9 +96,7 @@ export default function PinList({ id }) {
{noPins ? (
<div className="none">
<IconSurprise />
<div className="tip">
This channel doesnt have any pinned message yet.
</div>
<div className="tip">This channel doesnt have any pinned message yet.</div>
</div>
) : (
<ul className="list">
@@ -115,11 +113,7 @@ export default function PinList({ id }) {
<IconForward />
</button> */}
{canPin && (
<button
className="btn"
data-mid={mid}
onClick={handleUnpin}
>
<button className="btn" data-mid={mid} onClick={handleUnpin}>
<IconClose />
</button>
)}
+17 -29
View File
@@ -28,7 +28,7 @@ import {
// StyledNotification,
StyledContacts,
StyledChannelChat,
StyledHeader,
StyledHeader
} from "./styled";
import InviteModal from "../../../common/component/InviteModal";
import LoadMore from "../LoadMore";
@@ -36,9 +36,14 @@ import LoadMore from "../LoadMore";
export default function ChannelChat({ cid = "", dropFiles = [] }) {
const { values: agoraConfig } = useConfig("agora");
const { list: msgIds, appends, hasMore, pullUp } = useMessageFeed({
const {
list: msgIds,
appends,
hasMore,
pullUp
} = useMessageFeed({
context: "channel",
id: cid,
id: cid
});
// const scrollObserveRef = useChatScroll([msgIds, appends]);
const [toolVisible, setToolVisible] = useState("");
@@ -56,7 +61,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
messageData,
loginUid,
loginUser,
footprint,
footprint
} = useSelector((store) => {
return {
selects: store.ui.selectMessages[`channel_${cid}`],
@@ -66,7 +71,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
// msgIds: store.channelMessage[cid] || [],
userIds: store.contacts.ids,
data: store.channels.byId[cid] || {},
messageData: store.message || {},
messageData: store.message || {}
};
});
// const ref = useChatScroll(msgIds);
@@ -88,9 +93,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
};
if (!data) return null;
const { name, description, is_public, members = [], owner } = data;
const memberIds = is_public
? userIds
: members.slice(0).sort((n) => (n == owner ? -1 : 0));
const memberIds = is_public ? userIds : members.slice(0).sort((n) => (n == owner ? -1 : 0));
const addVisible = loginUser?.is_admin || owner == loginUid;
console.log("channel message list", msgIds);
const readIndex = footprint.readChannels[cid];
@@ -98,9 +101,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
const feeds = [...msgIds, ...appends];
return (
<>
{addMemberModalVisible && (
<InviteModal cid={cid} closeModal={toggleAddVisible} />
)}
{addMemberModalVisible && <InviteModal cid={cid} closeModal={toggleAddVisible} />}
<Layout
to={cid}
context="channel"
@@ -116,11 +117,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
</Tooltip>
</li>
)}
<Tooltip
tip="Pin"
placement="left"
disabled={toolVisible == "pin"}
>
<Tooltip tip="Pin" placement="left" disabled={toolVisible == "pin"}>
<Tippy
onShow={() => {
setToolVisible("pin");
@@ -145,11 +142,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
</li>
</Tippy>
</Tooltip>
<Tooltip
tip="Favorite"
placement="left"
disabled={toolVisible == "favorite"}
>
<Tooltip tip="Favorite" placement="left" disabled={toolVisible == "favorite"}>
<Tippy
onShow={() => {
setToolVisible("favorite");
@@ -165,9 +158,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
content={<FavList cid={cid} />}
>
<li
className={`tool fav ${
toolVisible == "favorite" ? "active" : ""
} `}
className={`tool fav ${toolVisible == "favorite" ? "active" : ""} `}
data-count={pinCount}
>
<IconFav />
@@ -246,10 +237,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
<div className="info">
<h2 className="title">Welcome to #{name} !</h2>
<p className="desc">This is the start of the #{name} channel. </p>
<NavLink
to={`/setting/channel/${cid}?f=${pathname}`}
className="edit"
>
<NavLink to={`/setting/channel/${cid}?f=${pathname}`} className="edit">
<EditIcon className="icon" />
Edit Channel
</NavLink>
@@ -270,7 +258,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
prev,
curr,
contextId: cid,
context: "channel",
context: "channel"
});
})}
+13 -17
View File
@@ -29,7 +29,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
visible: contextMenuVisible,
offset,
handleContextMenuEvent,
hideContextMenu,
hideContextMenu
} = useContextMenu();
const {
channel,
@@ -37,7 +37,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
messageData,
readIndex,
muted,
loginUid,
loginUid
// loginUser,
} = useSelector((store) => {
return {
@@ -47,7 +47,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
messageData: store.message,
loginUid: store.authData.uid,
readIndex: store.footprint.readChannels[id],
muted: store.footprint.muteChannels[id],
muted: store.footprint.muteChannels[id]
};
});
const handleChannelSetting = (evt) => {
@@ -72,8 +72,8 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
}
},
collect: (monitor) => ({
isActive: monitor.canDrop() && monitor.isOver(),
}),
isActive: monitor.canDrop() && monitor.isOver()
})
}));
const handleReadAll = () => {
const lastMid = mids[mids.length - 1];
@@ -91,9 +91,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
setInviteModalVisible((prev) => !prev);
};
const handleMute = () => {
const data = muted
? { remove_groups: [id] }
: { add_groups: [{ gid: id }] };
const data = muted ? { remove_groups: [id] } : { add_groups: [{ gid: id }] };
muteChannel(data);
};
const { is_public, name, owner } = channel;
@@ -101,7 +99,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
mids,
messageData,
readIndex,
loginUid,
loginUid
});
const isMentions = mentions.length !== 0;
const inviteIconVisible = is_public || owner == loginUid;
@@ -122,11 +120,11 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
{
title: "Mark As Read",
underline: true,
handler: handleReadAll,
handler: handleReadAll
},
{
title: muted ? "Unmute" : "Mute",
handler: handleMute,
handler: handleMute
},
// {
// title: "Notification Settings",
@@ -134,13 +132,13 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
// },
{
title: "Invite People",
handler: toggleInviteModalVisible,
handler: toggleInviteModalVisible
},
{
title: "Delete Channel",
danger: true,
handler: toggleRemoveConfirm.bind(null, id),
},
handler: toggleRemoveConfirm.bind(null, id)
}
]}
/>
}
@@ -150,9 +148,7 @@ const NavItem = ({ id, setFiles, toggleRemoveConfirm }) => {
onContextMenu={handleContextMenuEvent}
ref={drop}
key={id}
className={`link ${isActive ? "drop_over" : ""} ${
muted ? "muted" : ""
}`}
className={`link ${isActive ? "drop_over" : ""} ${muted ? "muted" : ""}`}
activeclassname="link_active"
to={`/chat/channel/${id}`}
>
+17 -14
View File
@@ -20,25 +20,28 @@ import LoadMore from "../LoadMore";
import { renderMessageFragment } from "../utils";
import useMessageFeed from "../../../common/hook/useMessageFeed";
export default function DMChat({ uid = "", dropFiles = [] }) {
const { list: msgIds, appends, hasMore, pullUp } = useMessageFeed({
const {
list: msgIds,
appends,
hasMore,
pullUp
} = useMessageFeed({
context: "user",
id: uid,
id: uid
});
const [updateReadIndex] = useReadMessageMutation();
const updateReadDebounced = useDebounce(updateReadIndex, 300);
console.log("dm files", dropFiles);
// const [mids, setMids] = useState([]);
const { currUser, messageData, footprint, loginUid, selects } = useSelector(
(store) => {
return {
selects: store.ui.selectMessages[`user_${uid}`],
loginUid: store.authData.uid,
footprint: store.footprint,
currUser: store.contacts.byId[uid],
messageData: store.message,
};
}
);
const { currUser, messageData, footprint, loginUid, selects } = useSelector((store) => {
return {
selects: store.ui.selectMessages[`user_${uid}`],
loginUid: store.authData.uid,
footprint: store.footprint,
currUser: store.contacts.byId[uid],
messageData: store.message
};
});
// const ref = useChatScroll(msgIds);
if (!currUser) return null;
@@ -111,7 +114,7 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
prev,
curr,
contextId: uid,
context: "user",
context: "user"
});
})}
</StyledDMChat>
+9 -18
View File
@@ -18,25 +18,18 @@ import Contact from "../../../common/component/Contact";
import { ContentTypes } from "../../../app/config";
const NavItem = ({ uid, mid, unreads, setFiles }) => {
const [previewMsg, setPreviewMsg] = useState(null);
const {
messages: normalizedMessages,
normalizeMessage,
} = useNormalizeMessage();
const { messages: normalizedMessages, normalizeMessage } = useNormalizeMessage();
const dispatch = useDispatch();
const pathMatched = useMatch(`/chat/dm/${uid}`);
const [updateReadIndex] = useReadMessageMutation();
const { currMsg, currUser } = useSelector((store) => {
return {
currUser: store.contacts.byId[uid],
currMsg: store.message[mid],
currMsg: store.message[mid]
};
});
const navigate = useNavigate();
const {
visible: contextMenuVisible,
handleContextMenuEvent,
hideContextMenu,
} = useContextMenu();
const { visible: contextMenuVisible, handleContextMenuEvent, hideContextMenu } = useContextMenu();
const [{ isActive }, drop] = useDrop(() => ({
accept: [NativeTypes.FILE],
drop({ dataTransfer }) {
@@ -51,8 +44,8 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
}
},
collect: (monitor) => ({
isActive: monitor.canDrop() && monitor.isOver(),
}),
isActive: monitor.canDrop() && monitor.isOver()
})
}));
useEffect(() => {
if (currMsg) {
@@ -96,13 +89,13 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
items={[
{
title: "Mark As Read",
handler: handleReadAll,
handler: handleReadAll
},
{
title: "Hide Session",
danger: true,
handler: handleRemoveSession,
},
handler: handleRemoveSession
}
]}
/>
}
@@ -118,9 +111,7 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
<div className="details">
<div className="up">
<span className="name">{currUser.name}</span>
{previewMsg && (
<time>{dayjs(previewMsg.created_at).fromNow()}</time>
)}
{previewMsg && <time>{dayjs(previewMsg.created_at).fromNow()}</time>}
</div>
<div className="down">
+11 -19
View File
@@ -5,17 +5,15 @@ import { getUnreadCount } from "../utils";
import NavItem from "./NavItem";
export default function DMList({ uids, setDropFiles }) {
const { userMessage, messageData, readUsers, loginUid } = useSelector(
(store) => {
return {
loginUid: store.authData.uid,
readUsers: store.footprint.readUsers,
contactData: store.contacts.byId,
userMessage: store.userMessage.byId,
messageData: store.message,
};
}
);
const { userMessage, messageData, readUsers, loginUid } = useSelector((store) => {
return {
loginUid: store.authData.uid,
readUsers: store.footprint.readUsers,
contactData: store.contacts.byId,
userMessage: store.userMessage.byId,
messageData: store.message
};
});
const sessions = uids.map((uid) => {
const mids = userMessage[uid] || [];
if (mids.length == 0) {
@@ -27,7 +25,7 @@ export default function DMList({ uids, setDropFiles }) {
mids,
readIndex,
messageData,
loginUid,
loginUid
});
return { lastMid, unreads, uid };
@@ -40,13 +38,7 @@ export default function DMList({ uids, setDropFiles }) {
})
.map(({ lastMid, uid, unreads }) => {
return (
<NavItem
key={uid}
uid={uid}
mid={lastMid}
unreads={unreads}
setFiles={setDropFiles}
/>
<NavItem key={uid} uid={uid} mid={lastMid} unreads={unreads} setFiles={setDropFiles} />
);
});
}
+1 -3
View File
@@ -97,9 +97,7 @@ export default function FavList({ cid = null, uid = null }) {
{noFavs ? (
<div className="none">
<IconSurprise />
<div className="tip">
This channel doesnt have any saved message yet.
</div>
<div className="tip">This channel doesnt have any saved message yet.</div>
</div>
) : (
<ul className="list">
+3 -11
View File
@@ -44,9 +44,7 @@ export default function Operations({ context, id }) {
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const { canDelete } = useDeleteMessage();
const { addFavorite } = useFavMessage({});
const mids = useSelector(
(store) => store.ui.selectMessages[`${context}_${id}`]
);
const mids = useSelector((store) => store.ui.selectMessages[`${context}_${id}`]);
const [forwardModalVisible, setForwardModalVisible] = useState(false);
const dispatch = useDispatch();
const handleClose = () => {
@@ -86,18 +84,12 @@ export default function Operations({ context, id }) {
<button className="opt" onClick={handleFav}>
<IconBookmark />
</button>
<button
className="opt"
disabled={!canDel}
onClick={toggleDeleteModal.bind(null, false)}
>
<button className="opt" disabled={!canDel} onClick={toggleDeleteModal.bind(null, false)}>
<IconDelete />
</button>
<IconClose className="close" onClick={handleClose} />
</Styled>
{forwardModalVisible && (
<ForwardModal mids={mids} closeModal={toggleForwardModal} />
)}
{forwardModalVisible && <ForwardModal mids={mids} closeModal={toggleForwardModal} />}
{deleteModalVisible && (
<DeleteMessageConfirmModal mids={mids} closeModal={toggleDeleteModal} />
)}
+10 -26
View File
@@ -17,7 +17,7 @@ export default function Layout({
contacts = null,
dropFiles = [],
context = "channel",
to = null,
to = null
}) {
const { addStageFile } = useUploadFile({ context, id: to });
const messagesContainer = useRef(undefined);
@@ -26,7 +26,7 @@ export default function Layout({
return {
selects: store.ui.selectMessages[`${context}_${to}`],
channelsData: store.channels.byId,
contactsData: store.contacts.byId,
contactsData: store.contacts.byId
};
});
const [{ isActive }, drop] = useDrop(
@@ -44,8 +44,8 @@ export default function Layout({
}
},
collect: (monitor) => ({
isActive: monitor.canDrop() && monitor.isOver(),
}),
isActive: monitor.canDrop() && monitor.isOver()
})
}),
[context, to]
);
@@ -72,10 +72,7 @@ export default function Layout({
(evt) => {
console.log(evt);
const { target } = evt;
if (
target.nodeName == "IMG" &&
target.classList.contains("preview")
) {
if (target.nodeName == "IMG" && target.classList.contains("preview")) {
const thumbnail = target.src;
const originUrl = target.dataset.origin || target.src;
const downloadLink = target.dataset.download || target.src;
@@ -87,13 +84,10 @@ export default function Layout({
);
}
}, []);
const name =
context == "channel" ? channelsData[to]?.name : contactsData[to]?.name;
const name = context == "channel" ? channelsData[to]?.name : contactsData[to]?.name;
return (
<>
{previewImage && (
<ImagePreviewModal data={previewImage} closeModal={closePreviewModal} />
)}
{previewImage && <ImagePreviewModal data={previewImage} closeModal={closePreviewModal} />}
<Styled ref={drop}>
{header}
<main className="main" ref={messagesContainer}>
@@ -107,21 +101,11 @@ export default function Layout({
{contacts && <div className="members">{contacts}</div>}
{aside && <div className="aside">{aside}</div>}
</main>
<div
className={`drag_tip ${
isActive ? "visible animate__animated animate__fadeIn" : ""
}`}
>
<div
className={`box ${
isActive ? "animate__animated animate__bounceIn" : ""
}`}
>
<div className={`drag_tip ${isActive ? "visible animate__animated animate__fadeIn" : ""}`}>
<div className={`box ${isActive ? "animate__animated animate__bounceIn" : ""}`}>
<div className="inner">
<h4 className="head">{`Send to ${ChatPrefixs[context]}${name}`}</h4>
<span className="intro">
Photos accept jpg, png, max size limit to 10M.
</span>
<span className="intro">Photos accept jpg, png, max size limit to 10M.</span>
</div>
</div>
</div>
+1 -7
View File
@@ -40,13 +40,7 @@ export default function LoadMore({ pullUp = null }) {
}, [ref, pullUp]);
return (
<Styled ref={ref}>
<Waveform
className="loading"
size={24}
lineWeight={5}
speed={1}
color="#ccc"
/>
<Waveform className="loading" size={24} lineWeight={5} speed={1} color="#ccc" />
</Styled>
);
}
+8 -27
View File
@@ -24,7 +24,7 @@ export default function ChatPage() {
const [userDropFiles, setUserDropFiles] = useState([]);
const { sessionUids } = useSelector((store) => {
return {
sessionUids: store.userMessage.ids,
sessionUids: store.userMessage.ids
};
});
const [channelModalVisible, setChannelModalVisible] = useState(false);
@@ -41,8 +41,7 @@ export default function ChatPage() {
const listEle = currentTarget.parentElement.parentElement;
listEle.classList.toggle("collapse");
};
const tmpUid =
sessionUids.findIndex((i) => i == user_id) > -1 ? null : user_id;
const tmpUid = sessionUids.findIndex((i) => i == user_id) > -1 ? null : user_id;
// console.log("temp uid", tmpUid);
const placeholderVisible = !channel_id && !user_id;
return (
@@ -50,27 +49,18 @@ export default function ChatPage() {
{channelModalVisible && (
<ChannelModal closeModal={toggleChannelModalVisible} personal={true} />
)}
{contactsModalVisible && (
<ContactsModal closeModal={toggleContactsModalVisible} />
)}
{contactsModalVisible && <ContactsModal closeModal={toggleContactsModalVisible} />}
<StyledWrapper>
<div className="left">
<Server />
<div className="list channels">
<h3 className="title">
<span className="txt" onClick={handleToggleExpand}>
<AiOutlineCaretDown
className="icon"
size={18}
color="#78787C"
/>
<AiOutlineCaretDown className="icon" size={18} color="#78787C" />
CHANNELS
</span>
<Tooltip tip="New Channel" placement="bottom">
<AddIcon
className="add_icon"
onClick={toggleChannelModalVisible}
/>
<AddIcon className="add_icon" onClick={toggleChannelModalVisible} />
</Tooltip>
</h3>
<nav className="nav">
@@ -80,18 +70,11 @@ export default function ChatPage() {
<div className="list dms">
<h3 className="title">
<span className="txt" onClick={handleToggleExpand}>
<AiOutlineCaretDown
className="icon"
size={18}
color="#78787C"
/>
<AiOutlineCaretDown className="icon" size={18} color="#78787C" />
DIRECT MESSAGE
</span>
<Tooltip tip="New DM" placement="bottom">
<AddIcon
className="add_icon"
onClick={toggleContactsModalVisible}
/>
<AddIcon className="add_icon" onClick={toggleContactsModalVisible} />
</Tooltip>
</h3>
<nav className="nav">
@@ -105,9 +88,7 @@ export default function ChatPage() {
</div>
<div className={`right ${placeholderVisible ? "placeholder" : ""}`}>
{placeholderVisible && <BlankPlaceholder />}
{channel_id && (
<ChannelChat cid={channel_id} dropFiles={channelDropFiles} />
)}
{channel_id && <ChannelChat cid={channel_id} dropFiles={channelDropFiles} />}
{user_id && <DMChat uid={user_id} dropFiles={userDropFiles} />}
</div>
</StyledWrapper>
+5 -24
View File
@@ -20,12 +20,7 @@ import { updateSelectMessages } from "../../app/slices/ui";
// }
// };
// }
export function getUnreadCount({
mids = [],
messageData = {},
loginUid = 0,
readIndex = 0,
}) {
export function getUnreadCount({ mids = [], messageData = {}, loginUid = 0, readIndex = 0 }) {
// console.log({ mids, loginUid, readIndex });
// 先过滤掉空信息和from自己的
const others = mids.filter((mid) => {
@@ -123,19 +118,10 @@ const StyledWrapper = styled.div`
}
}
`;
const MessageWrapper = ({
selectMode = false,
context,
id,
mid,
children,
...rest
}) => {
const MessageWrapper = ({ selectMode = false, context, id, mid, children, ...rest }) => {
const dispatch = useDispatch();
const selects = useSelector(
(store) => store.ui.selectMessages[`${context}_${id}`]
);
const selects = useSelector((store) => store.ui.selectMessages[`${context}_${id}`]);
const selected = !!(selects && selects.find((s) => s == mid));
const toggleSelect = () => {
const operation = selected ? "remove" : "add";
@@ -146,12 +132,7 @@ const MessageWrapper = ({
<Checkbox className="check" checked={selected} />
{/* {React.cloneElement(children, { readOnly: selected })} */}
{children}
{selectMode && (
<div
className="overlay"
onClick={selectMode ? toggleSelect : null}
></div>
)}
{selectMode && <div className="overlay" onClick={selectMode ? toggleSelect : null}></div>}
</StyledWrapper>
);
};
@@ -163,7 +144,7 @@ export const renderMessageFragment = ({
prev = null,
curr = null,
contextId = 0,
context = "user",
context = "user"
}) => {
if (!curr) return null;
let { created_at, mid } = curr;
+11 -20
View File
@@ -14,12 +14,12 @@ const Filters = [
{
icon: <IconUnkown className="icon" />,
title: "All Items",
filter: "",
filter: ""
},
{
icon: <IconImage className="icon" />,
title: "Images",
filter: "image",
filter: "image"
},
// {
// icon: <IconDoc className="icon" />,
@@ -29,13 +29,13 @@ const Filters = [
{
icon: <IconVideo className="icon" />,
title: "Videos",
filter: "video",
filter: "video"
},
{
icon: <IconAudio className="icon" />,
title: "Audios",
filter: "audio",
},
filter: "audio"
}
];
function FavsPage() {
const [filter, setFilter] = useState("");
@@ -45,7 +45,7 @@ function FavsPage() {
return {
favorites: store.favorites,
userData: store.contacts.byId,
channelData: store.channels.byId,
channelData: store.channels.byId
};
});
const handleFilter = (ftr) => {
@@ -64,10 +64,7 @@ function FavsPage() {
const msgs = f.messages || [];
return msgs.every((m) => {
const file_type = m.properties?.content_type;
return (
m.content_type == ContentTypes.file &&
file_type.startsWith("audio")
);
return m.content_type == ContentTypes.file && file_type.startsWith("audio");
});
})
);
@@ -80,10 +77,7 @@ function FavsPage() {
const msgs = f.messages || [];
return msgs.every((m) => {
const file_type = m.properties?.content_type;
return (
m.content_type == ContentTypes.file &&
file_type.startsWith("video")
);
return m.content_type == ContentTypes.file && file_type.startsWith("video");
});
})
);
@@ -106,10 +100,7 @@ function FavsPage() {
const msgs = f.messages || [];
return msgs.every((m) => {
const file_type = m.properties?.content_type;
return (
m.content_type == ContentTypes.file &&
file_type.startsWith("image")
);
return m.content_type == ContentTypes.file && file_type.startsWith("image");
});
});
setFavs(tmps);
@@ -144,8 +135,8 @@ function FavsPage() {
{favs.map(({ id, created_at, messages }) => {
const [
{
source: { gid, uid },
},
source: { gid, uid }
}
] = messages;
const tip = gid ? (
<span className="from channel">
+1 -3
View File
@@ -48,9 +48,7 @@ export default function ServerDropList({ data, memberCount, expand = true }) {
<img className="logo" src={data.logo} alt="logo" />
{expand && (
<div className="info">
<h2 className="title animate__animated animate__fadeIn">
{data.name}
</h2>
<h2 className="title animate__animated animate__fadeIn">{data.name}</h2>
<span className="count">{memberCount} members</span>
</div>
)}
+3 -13
View File
@@ -73,29 +73,19 @@ export default function Tools({ expand = true }) {
alt="logo"
/>
</div>
{expand && (
<h2 className="title animate__animated animate__fadeIn">
Webrowse
</h2>
)}
{expand && <h2 className="title animate__animated animate__fadeIn">Webrowse</h2>}
</li>
<li className="tool">
<div className="logo">
<IoLogoGithub size={40} className="icon" />
</div>
{expand && (
<h2 className="title animate__animated animate__fadeIn">Github</h2>
)}
{expand && <h2 className="title animate__animated animate__fadeIn">Github</h2>}
</li>
<li className="tool add">
<div className="logo">
<RiAddFill className="icon" size={40} color="#4B5563" />
</div>
{expand && (
<h2 className="title animate__animated animate__fadeIn">
Add new app
</h2>
)}
{expand && <h2 className="title animate__animated animate__fadeIn">Add new app</h2>}
</li>
</ul>
</StyledWrapper>
+4 -7
View File
@@ -27,12 +27,12 @@ export default function HomePage() {
loginUid,
ui: {
ready,
remeberedNavs: { chat: chatPath, contact: contactPath },
},
remeberedNavs: { chat: chatPath, contact: contactPath }
}
} = useSelector((store) => {
return {
ui: store.ui,
loginUid: store.authData.uid,
loginUid: store.authData.uid
};
});
const { loading } = usePreload();
@@ -61,10 +61,7 @@ export default function HomePage() {
<div className={`col left`}>
<User uid={loginUid} />
<nav className="link_navs">
<NavLink
className={`link ${isHomePath ? "active" : ""}`}
to={chatNav}
>
<NavLink className={`link ${isHomePath ? "active" : ""}`} to={chatNav}>
<Tooltip tip="Chat">
<ChatIcon />
</Tooltip>
+8 -14
View File
@@ -22,8 +22,8 @@ export default function usePreload() {
isLoading: favoritesLoading,
isSuccess: favoritesSuccess,
isError: favoritesError,
data: favorites,
},
data: favorites
}
] = useLazyGetFavoritesQuery();
const [
getContacts,
@@ -31,17 +31,12 @@ export default function usePreload() {
isLoading: contactsLoading,
isSuccess: contactsSuccess,
isError: contactsError,
data: contacts,
},
data: contacts
}
] = useLazyGetContactsQuery();
const [
getServer,
{
isLoading: serverLoading,
isSuccess: serverSuccess,
isError: serverError,
data: server,
},
{ isLoading: serverLoading, isSuccess: serverSuccess, isError: serverError, data: server }
] = useLazyGetServerQuery();
useEffect(() => {
initCache();
@@ -64,14 +59,13 @@ export default function usePreload() {
}, [canStreaming]);
return {
loading:
contactsLoading || serverLoading || favoritesLoading || !rehydrated,
loading: contactsLoading || serverLoading || favoritesLoading || !rehydrated,
error: contactsError && serverError && favoritesError,
success: contactsSuccess && serverSuccess && favoritesSuccess,
data: {
contacts,
server,
favorites,
},
favorites
}
};
}
+1 -1
View File
@@ -29,7 +29,7 @@ import store from "../app/store";
const PageRoutes = () => {
const {
ui: { online },
fileMessages,
fileMessages
} = useSelector((store) => {
return { ui: store.ui, fileMessages: store.fileMessage };
});
+8 -21
View File
@@ -15,14 +15,9 @@ export default function InvitePage() {
const [valid, setValid] = useState(false);
// const [sp] = useSearchParams();
// const navigateTo = useNavigate();
const [
register,
{ data, isLoading, isSuccess, isError, error },
] = useRegisterMutation();
const [
checkToken,
{ data: isValid, isLoading: checkLoading, isSuccess: checkSuccess },
] = useCheckInviteTokenValidMutation();
const [register, { data, isLoading, isSuccess, isError, error }] = useRegisterMutation();
const [checkToken, { data: isValid, isLoading: checkLoading, isSuccess: checkSuccess }] =
useCheckInviteTokenValidMutation();
useEffect(() => {
// console.log(search);
const query = new URLSearchParams(location.search);
@@ -45,7 +40,7 @@ export default function InvitePage() {
const [input, setInput] = useState({
name: "",
email: "",
password: "",
password: ""
});
const handleReg = (evt) => {
@@ -58,7 +53,7 @@ export default function InvitePage() {
register({
...input,
magic_token: token,
gender: 1,
gender: 1
});
};
const handleInput = (evt) => {
@@ -105,7 +100,7 @@ export default function InvitePage() {
case 409: {
const tips = {
email_conflict: "email conflict",
name_conflict: "name conflict",
name_conflict: "name conflict"
};
toast.error(`Register Failed: ${tips[error.data?.reason]}`);
break;
@@ -126,11 +121,7 @@ export default function InvitePage() {
<StyledWrapper>
<div className="form animate__animated animate__fadeInDown animate__faster">
<div className="tips">
<img
src={`${BASE_URL}/resource/organization/logo`}
alt="logo"
className="logo"
/>
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
<h2 className="title">Sign Up to Rustchat</h2>
<span className="desc">Please enter your details.</span>
</div>
@@ -170,11 +161,7 @@ export default function InvitePage() {
onChange={handleSecondPwdInput}
placeholder="Enter your password again"
/>
<button
disabled={isLoading || isSuccess}
className="btn"
type="submit"
>
<button disabled={isLoading || isSuccess} className="btn" type="submit">
Sign Up
</button>
</form>
+70 -70
View File
@@ -1,75 +1,75 @@
import styled from 'styled-components';
import styled from "styled-components";
const StyledWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
.form {
padding: 36px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 24px;
.logo {
width: 56px;
height: 56px;
margin-bottom: 28px;
}
.title {
font-weight: 600;
font-size: 24px;
line-height: 32px;
color: #101828;
margin-bottom: 8px;
}
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
.form {
padding: 36px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 24px;
.logo {
width: 56px;
height: 56px;
margin-bottom: 28px;
}
.title {
font-weight: 600;
font-size: 24px;
line-height: 32px;
color: #101828;
margin-bottom: 8px;
}
}
.desc {
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
form {
display: flex;
flex-direction: column;
gap: 20px;
input {
width: 360px;
background: #ffffff;
border: 1px solid #d0d5dd;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
padding: 10px 14px;
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
}
.btn {
display: inline-block;
text-align: center;
width: 100%;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #ffffff;
padding: 10px;
background: #1fe1f9;
border: 1px solid #1fe1f9;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
&.google {
color: #344054;
border-color: #d0d5dd;
background: none;
}
}
}
.desc {
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
form {
display: flex;
flex-direction: column;
gap: 20px;
input {
width: 360px;
background: #ffffff;
border: 1px solid #d0d5dd;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
padding: 10px 14px;
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
}
.btn {
display: inline-block;
text-align: center;
width: 100%;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #ffffff;
padding: 10px;
background: #1fe1f9;
border: 1px solid #1fe1f9;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
&.google {
color: #344054;
border-color: #d0d5dd;
background: none;
}
}
}
`;
export default StyledWrapper;
+2 -2
View File
@@ -13,12 +13,12 @@ export default function GoogleLoginButton({ login, clientId }) {
console.info("google oauth success", tokenId, rest);
login({
id_token: tokenId,
type: "google",
type: "google"
});
},
onFailure: (wtf) => {
console.error("google login failure", wtf);
},
}
});
const handleGoogleLogin = () => {
signIn();
+1 -5
View File
@@ -12,9 +12,5 @@ export default function MagicLinkLogin() {
navigate("/send_magic_link");
// signIn();
};
return (
<StyledMagicButton onClick={handleGoogleLogin}>
Sign in with Magic Link
</StyledMagicButton>
);
return <StyledMagicButton onClick={handleGoogleLogin}>Sign in with Magic Link</StyledMagicButton>;
}
+4 -4
View File
@@ -37,7 +37,7 @@ export default function MetamaskLoginButton({ login }) {
public_address: address,
nonce,
signature,
type: "metamask",
type: "metamask"
});
}
};
@@ -58,7 +58,7 @@ export default function MetamaskLoginButton({ login }) {
console.log("get sn");
const signature = await ethereum.request({
method: "personal_sign",
params: [nonce, address, "hello from rustchat"],
params: [nonce, address, "hello from rustchat"]
});
return signature;
};
@@ -68,14 +68,14 @@ export default function MetamaskLoginButton({ login }) {
setRequesting(true);
try {
const tmps = await ethereum.request({
method: "eth_requestAccounts",
method: "eth_requestAccounts"
});
setAccounts(tmps);
} catch (error) {
// toast.error(error.message);
ethereum.request({
method: "wallet_requestPermissions",
params: [{ eth_accounts: {} }],
params: [{ eth_accounts: {} }]
});
// setRequesting(false);
}
+1 -1
View File
@@ -11,7 +11,7 @@ export default function SolidLoginButton({ issuers }) {
getOpenId({
// issuer: "solidweb.org",
issuer: issuers[0],
redirect_uri: `${location.origin}/#/login`,
redirect_uri: `${location.origin}/#/login`
});
};
useEffect(() => {
+10 -24
View File
@@ -11,10 +11,7 @@ import Button from "../../common/component/styled/Button";
import GoogleLoginButton from "./GoogleLoginButton";
import MagicLinkLogin from "./MagicLinkLogin";
import { useLoginMutation } from "../../app/services/auth";
import {
useGetLoginConfigQuery,
useGetSMTPStatusQuery,
} from "../../app/services/server";
import { useGetLoginConfigQuery, useGetSMTPStatusQuery } from "../../app/services/server";
import useGoogleAuthConfig from "../../common/hook/useGoogleAuthConfig";
import GithubLoginButton from "./GithubLoginButton";
import useGithubAuthConfig from "../../common/hook/useGithubAuthConfig";
@@ -23,13 +20,10 @@ export default function LoginPage() {
const [login, { isSuccess, isLoading, error }] = useLoginMutation();
const { clientId } = useGoogleAuthConfig();
const { config: githubAuthConfig } = useGithubAuthConfig();
const {
data: loginConfig,
isSuccess: loginConfigSuccess,
} = useGetLoginConfigQuery();
const { data: loginConfig, isSuccess: loginConfigSuccess } = useGetLoginConfigQuery();
const [input, setInput] = useState({
email: "",
password: "",
password: ""
});
useEffect(() => {
const query = new URLSearchParams(location.search);
@@ -45,7 +39,7 @@ export default function LoginPage() {
if (code) {
login({
code: code,
type: "github",
type: "github"
});
}
break;
@@ -54,7 +48,7 @@ export default function LoginPage() {
login({
code,
state,
type: "oidc",
type: "oidc"
});
}
break;
@@ -70,7 +64,7 @@ export default function LoginPage() {
// login
login({
token,
type: "magiclink",
type: "magiclink"
});
} else {
// reg
@@ -111,7 +105,7 @@ export default function LoginPage() {
console.log("wtf", input);
login({
...input,
type: "password",
type: "password"
});
};
@@ -131,25 +125,17 @@ export default function LoginPage() {
github: enableGithubLogin,
google: enableGoogleLogin,
metamask: enableMetamaskLogin,
oidc = [],
oidc = []
} = loginConfig;
const enableMagicLink = enableSMTP && magic_link;
const googleLogin = enableGoogleLogin && clientId;
const hasDivider =
enableMagicLink ||
googleLogin ||
enableMetamaskLogin ||
oidc.length > 0 ||
enableGithubLogin;
enableMagicLink || googleLogin || enableMetamaskLogin || oidc.length > 0 || enableGithubLogin;
return (
<StyledWrapper>
<div className="form">
<div className="tips">
<img
src={`${BASE_URL}/resource/organization/logo`}
alt="logo"
className="logo"
/>
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
<h2 className="title">Login to Rustchat</h2>
<span className="desc">Please enter your details.</span>
</div>
+1 -2
View File
@@ -23,8 +23,7 @@ const StyledWrapper = styled.div`
.form {
padding: 36px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1),
0px 2px 4px -2px rgba(16, 24, 40, 0.06);
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
+1 -4
View File
@@ -8,10 +8,7 @@ import toast from "react-hot-toast";
import { setAuthData } from "../../app/slices/auth.data";
export default function OAuthPage() {
const [
login,
{ data, isSuccess, isError, error: loginError },
] = useLoginMutation();
const [login, { data, isSuccess, isError, error: loginError }] = useLoginMutation();
const { token } = useParams();
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
+70 -70
View File
@@ -1,75 +1,75 @@
import styled from 'styled-components';
import styled from "styled-components";
const StyledWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
.form {
padding: 36px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 24px;
.logo {
width: 56px;
height: 56px;
margin-bottom: 28px;
}
.title {
font-weight: 600;
font-size: 24px;
line-height: 32px;
color: #101828;
margin-bottom: 8px;
}
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
.form {
padding: 36px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 24px;
.logo {
width: 56px;
height: 56px;
margin-bottom: 28px;
}
.title {
font-weight: 600;
font-size: 24px;
line-height: 32px;
color: #101828;
margin-bottom: 8px;
}
}
.desc {
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
form {
display: flex;
flex-direction: column;
gap: 20px;
input {
width: 360px;
background: #ffffff;
border: 1px solid #d0d5dd;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
padding: 10px 14px;
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
}
.btn {
display: inline-block;
text-align: center;
width: 100%;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #ffffff;
padding: 10px;
background: #1fe1f9;
border: 1px solid #1fe1f9;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
&.google {
color: #344054;
border-color: #d0d5dd;
background: none;
}
}
}
.desc {
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
form {
display: flex;
flex-direction: column;
gap: 20px;
input {
width: 360px;
background: #ffffff;
border: 1px solid #d0d5dd;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
padding: 10px 14px;
font-weight: normal;
font-size: 16px;
line-height: 24px;
color: #667085;
}
}
.btn {
display: inline-block;
text-align: center;
width: 100%;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #ffffff;
padding: 10px;
background: #1fe1f9;
border: 1px solid #1fe1f9;
box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
border-radius: 8px;
&.google {
color: #344054;
border-color: #d0d5dd;
background: none;
}
}
}
`;
export default StyledWrapper;
+21 -21
View File
@@ -10,26 +10,26 @@ import CompletedStep from "./steps/6-completed";
import StyledOnboardingPage from "./styled";
export default function OnboardingPage() {
const [step, setStep] = useState(0);
const [data, setData] = useState({
serverName: ""
});
const props = { setStep, data, setData };
const [step, setStep] = useState(0);
const [data, setData] = useState({
serverName: ""
});
const props = { setStep, data, setData };
return (
<>
<Helmet>
<title>Rustchat Setup</title>
</Helmet>
<StyledOnboardingPage>
{step === 0 && <WelcomeStep {...props} />}
{step === 1 && <ServerNameStep {...props} />}
{step === 2 && <AdminCredentialsStep {...props} />}
{step === 3 && <InviteRuleStep {...props} />}
{step === 4 && <InviteLinkStep {...props} />}
{step === 5 && <CompletedStep {...props} />}
{step === 6 && <Navigate replace to="/" />}
</StyledOnboardingPage>
</>
);
return (
<>
<Helmet>
<title>Rustchat Setup</title>
</Helmet>
<StyledOnboardingPage>
{step === 0 && <WelcomeStep {...props} />}
{step === 1 && <ServerNameStep {...props} />}
{step === 2 && <AdminCredentialsStep {...props} />}
{step === 3 && <InviteRuleStep {...props} />}
{step === 4 && <InviteLinkStep {...props} />}
{step === 5 && <CompletedStep {...props} />}
{step === 6 && <Navigate replace to="/" />}
</StyledOnboardingPage>
</>
);
}
+17 -17
View File
@@ -3,24 +3,24 @@ import StyledButton from "../../../common/component/styled/Button";
import PlayIcon from "../../../assets/icons/play.svg?url";
const StyledFirstStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;
export default function WelcomeStep({ setStep }) {
return (
<StyledFirstStep>
<span className="primaryText">Welcome to your Rustchat!</span>
<span className="secondaryText">
Everything in this space is owned by you. Lets set up your space!
</span>
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
<img src={PlayIcon} alt="play icon" />
<span>Start</span>
</StyledButton>
</StyledFirstStep>
);
return (
<StyledFirstStep>
<span className="primaryText">Welcome to your Rustchat!</span>
<span className="secondaryText">
Everything in this space is owned by you. Lets set up your space!
</span>
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
<img src={PlayIcon} alt="play icon" />
<span>Start</span>
</StyledButton>
</StyledFirstStep>
);
}
+43 -43
View File
@@ -4,52 +4,52 @@ import StyledInput from "../../../common/component/styled/Input";
import StyledButton from "../../../common/component/styled/Button";
const StyledSpaceNameStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .secondaryText {
color: #667085;
}
> .secondaryText {
color: #667085;
}
> .button {
margin-top: 24px;
}
> .button {
margin-top: 24px;
}
`;
export default function ServerNameStep({ setStep, data, setData }) {
return (
<StyledSpaceNameStep>
<span className="primaryText">Create a new server</span>
<span className="secondaryText">
Servers are shared environments where teams can work on projects and chat.
</span>
<StyledInput
className="input"
placeholder="Enter server name"
value={data.serverName}
onChange={(e) =>
setData({
...data,
serverName: e.target.value
})
}
/>
<StyledButton
className="button"
onClick={() => {
// Verification for space name
if (data.serverName === "") {
toast.error("Please enter server name!");
return;
}
setStep((prev) => prev + 1);
}}
>
Create Server
</StyledButton>
</StyledSpaceNameStep>
);
return (
<StyledSpaceNameStep>
<span className="primaryText">Create a new server</span>
<span className="secondaryText">
Servers are shared environments where teams can work on projects and chat.
</span>
<StyledInput
className="input"
placeholder="Enter server name"
value={data.serverName}
onChange={(e) =>
setData({
...data,
serverName: e.target.value
})
}
/>
<StyledButton
className="button"
onClick={() => {
// Verification for space name
if (data.serverName === "") {
toast.error("Please enter server name!");
return;
}
setStep((prev) => prev + 1);
}}
>
Create Server
</StyledButton>
</StyledSpaceNameStep>
);
}
+107 -107
View File
@@ -5,127 +5,127 @@ import { useDispatch } from "react-redux";
import StyledInput from "../../../common/component/styled/Input";
import StyledButton from "../../../common/component/styled/Button";
import {
useCreateAdminMutation,
useGetServerQuery,
useUpdateServerMutation
useCreateAdminMutation,
useGetServerQuery,
useUpdateServerMutation
} from "../../../app/services/server";
import { useLoginMutation } from "../../../app/services/auth";
import { updateInitialized } from "../../../app/slices/auth.data";
const StyledAdminCredentialsStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .input:not(:nth-last-child(2)) {
margin-bottom: 20px;
}
> .input:not(:nth-last-child(2)) {
margin-bottom: 20px;
}
> .button {
margin-top: 24px;
}
> .button {
margin-top: 24px;
}
`;
export default function AdminCredentialsStep({ data, setStep }) {
const dispatch = useDispatch();
const dispatch = useDispatch();
const [createAdmin, { isLoading: isSigningUp, error: signUpError }] = useCreateAdminMutation();
const [login, { isLoading: isLoggingIn, isSuccess: isLoggedIn, error: loginError }] =
useLoginMutation();
const { data: serverData } = useGetServerQuery();
const [updateServer, { isLoading: isUpdatingServer, isSuccess: isUpdatedServer }] =
useUpdateServerMutation();
const [createAdmin, { isLoading: isSigningUp, error: signUpError }] = useCreateAdminMutation();
const [login, { isLoading: isLoggingIn, isSuccess: isLoggedIn, error: loginError }] =
useLoginMutation();
const { data: serverData } = useGetServerQuery();
const [updateServer, { isLoading: isUpdatingServer, isSuccess: isUpdatedServer }] =
useUpdateServerMutation();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirm, setConfirm] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirm, setConfirm] = useState("");
// Display error
useEffect(() => {
if (signUpError === undefined) return;
toast.error(`Failed to sign up: ${signUpError.data}`);
}, [signUpError]);
useEffect(() => {
if (loginError === undefined) return;
toast.error(`Login failed: ${loginError.data}`);
}, [loginError]);
// Display error
useEffect(() => {
if (signUpError === undefined) return;
toast.error(`Failed to sign up: ${signUpError.data}`);
}, [signUpError]);
useEffect(() => {
if (loginError === undefined) return;
toast.error(`Login failed: ${loginError.data}`);
}, [loginError]);
// After logged in
useEffect(() => {
if (isLoggedIn) {
dispatch(updateInitialized(true));
setTimeout(() => {
// Set server name
updateServer({
...serverData,
name: data.serverName
});
}, 0);
}
}, [isLoggedIn]);
// After logged in
useEffect(() => {
if (isLoggedIn) {
dispatch(updateInitialized(true));
setTimeout(() => {
// Set server name
updateServer({
...serverData,
name: data.serverName
});
}, 0);
}
}, [isLoggedIn]);
// After updated server
useEffect(() => {
if (isUpdatedServer) {
setStep((prev) => prev + 1);
}
}, [isUpdatedServer]);
// After updated server
useEffect(() => {
if (isUpdatedServer) {
setStep((prev) => prev + 1);
}
}, [isUpdatedServer]);
return (
<StyledAdminCredentialsStep>
<span className="primaryText">Now lets set up your admin account</span>
<span className="secondaryText">You are the 1st user and admin of your space!</span>
<StyledInput
className="input"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<StyledInput
className="input"
type="password"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<StyledInput
className="input"
type="password"
placeholder="Confirm your password"
value={confirm}
onChange={(e) => setConfirm(e.target.value)}
/>
<StyledButton
className="button"
onClick={async () => {
// Verification for admin credentials
if (email === "") {
toast.error("Please enter admin email!");
return;
} else if (password === "") {
toast.error("Please enter admin password!");
return;
} else if (password !== confirm) {
toast.error("Two passwords do not match!");
return;
}
await createAdmin({
email,
name: "Admin",
password,
gender: 0
});
await login({
email,
password,
type: "password"
});
}}
>
{!(isSigningUp || isLoggingIn || isUpdatingServer) ? "Sign Up" : "..."}
</StyledButton>
</StyledAdminCredentialsStep>
);
return (
<StyledAdminCredentialsStep>
<span className="primaryText">Now lets set up your admin account</span>
<span className="secondaryText">You are the 1st user and admin of your space!</span>
<StyledInput
className="input"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<StyledInput
className="input"
type="password"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<StyledInput
className="input"
type="password"
placeholder="Confirm your password"
value={confirm}
onChange={(e) => setConfirm(e.target.value)}
/>
<StyledButton
className="button"
onClick={async () => {
// Verification for admin credentials
if (email === "") {
toast.error("Please enter admin email!");
return;
} else if (password === "") {
toast.error("Please enter admin password!");
return;
} else if (password !== confirm) {
toast.error("Two passwords do not match!");
return;
}
await createAdmin({
email,
name: "Admin",
password,
gender: 0
});
await login({
email,
password,
type: "password"
});
}}
>
{!(isSigningUp || isLoggingIn || isUpdatingServer) ? "Sign Up" : "..."}
</StyledButton>
</StyledAdminCredentialsStep>
);
}
+46 -43
View File
@@ -6,55 +6,58 @@ import StyledButton from "../../../common/component/styled/Button";
import { useGetLoginConfigQuery, useUpdateLoginConfigMutation } from "../../../app/services/server";
const StyledInviteRuleStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .input:not(:nth-last-child(2)) {
margin-bottom: 20px;
}
> .input:not(:nth-last-child(2)) {
margin-bottom: 20px;
}
`;
export default function InviteRuleStep({ setStep }) {
const { data: loginConfig } = useGetLoginConfigQuery();
const [updateLoginConfig, { isSuccess, error }] = useUpdateLoginConfigMutation();
const { data: loginConfig } = useGetLoginConfigQuery();
const [updateLoginConfig, { isSuccess, error }] = useUpdateLoginConfigMutation();
const [value, setValue] = useState(0);
const [value, setValue] = useState(0);
// Display error
useEffect(() => {
if (error === undefined) return;
toast.error(`Failed to update invitation rule: ${error.data}`);
}, [error]);
// Display error
useEffect(() => {
if (error === undefined) return;
toast.error(`Failed to update invitation rule: ${error.data}`);
}, [error]);
// Increment `step` when updating has completed
useEffect(() => {
if (isSuccess) setStep((prev) => prev + 1);
}, [isSuccess]);
// Increment `step` when updating has completed
useEffect(() => {
if (isSuccess) setStep((prev) => prev + 1);
}, [isSuccess]);
return (
<StyledInviteRuleStep>
<span className="primaryText">Last step: invite others!</span>
<span className="secondaryText">Firstly, who can sign up to this server?</span>
<StyledRadio
options={["Everyone", "Invitation link only"]}
value={value}
onChange={async (v) => {
setValue(v);
if (loginConfig !== undefined) {
const whoCanSignUp = ["EveryOne", "InvitationOnly"][v];
await updateLoginConfig({
...loginConfig,
who_can_sign_up: whoCanSignUp
});
}
}}
/>
<StyledButton className="button border_less ghost" onClick={() => setStep((prev) => prev + 1)}>
Skip
</StyledButton>
</StyledInviteRuleStep>
);
return (
<StyledInviteRuleStep>
<span className="primaryText">Last step: invite others!</span>
<span className="secondaryText">Firstly, who can sign up to this server?</span>
<StyledRadio
options={["Everyone", "Invitation link only"]}
value={value}
onChange={async (v) => {
setValue(v);
if (loginConfig !== undefined) {
const whoCanSignUp = ["EveryOne", "InvitationOnly"][v];
await updateLoginConfig({
...loginConfig,
who_can_sign_up: whoCanSignUp
});
}
}}
/>
<StyledButton
className="button border_less ghost"
onClick={() => setStep((prev) => prev + 1)}
>
Skip
</StyledButton>
</StyledInviteRuleStep>
);
}
+60 -57
View File
@@ -4,70 +4,73 @@ import StyledButton from "../../../common/component/styled/Button";
import useInviteLink from "../../../common/hook/useInviteLink";
const StyledInviteLinkStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .secondaryText {
margin-bottom: 40px;
}
> .tip {
font-weight: 600;
font-size: 14px;
line-height: 20px;
color: #475467;
margin-bottom: 8px;
}
> .link {
position: relative;
background: #ffffff;
border: 1px solid #f4f4f5;
box-shadow: 0 1px 2px rgba(31, 41, 55, 0.08);
border-radius: 4px;
width: 374px;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> input {
border: none;
box-shadow: none;
padding: 11px 0 11px 8px;
font-weight: 400;
font-size: 14px;
line-height: 20px;
color: #78787c;
> .secondaryText {
margin-bottom: 40px;
}
> button {
padding: 0 8px;
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #22ccee;
> .tip {
font-weight: 600;
font-size: 14px;
line-height: 20px;
color: #475467;
margin-bottom: 8px;
}
> .link {
position: relative;
background: #ffffff;
border: 1px solid #f4f4f5;
box-shadow: 0 1px 2px rgba(31, 41, 55, 0.08);
border-radius: 4px;
width: 374px;
display: flex;
> input {
border: none;
box-shadow: none;
padding: 11px 0 11px 8px;
font-weight: 400;
font-size: 14px;
line-height: 20px;
color: #78787c;
}
> button {
padding: 0 8px;
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #22ccee;
}
}
}
`;
export default function InviteLinkStep({ setStep }) {
const { link, linkCopied, copyLink } = useInviteLink();
const { link, linkCopied, copyLink } = useInviteLink();
return (
<StyledInviteLinkStep>
<span className="primaryText">Last step: invite others!</span>
<span className="secondaryText">Now lets invite others!</span>
<span className="tip">Send invitation link to your future community members:</span>
<div className="link">
<StyledInput className="large" readOnly placeholder="Generating" value={link} />
<StyledButton onClick={copyLink} className="ghost small border_less">
{linkCopied ? "Copied" : `Copy`}
</StyledButton>
</div>
<StyledButton className="button border_less ghost" onClick={() => setStep((prev) => prev + 1)}>
Skip
</StyledButton>
</StyledInviteLinkStep>
);
return (
<StyledInviteLinkStep>
<span className="primaryText">Last step: invite others!</span>
<span className="secondaryText">Now lets invite others!</span>
<span className="tip">Send invitation link to your future community members:</span>
<div className="link">
<StyledInput className="large" readOnly placeholder="Generating" value={link} />
<StyledButton onClick={copyLink} className="ghost small border_less">
{linkCopied ? "Copied" : `Copy`}
</StyledButton>
</div>
<StyledButton
className="button border_less ghost"
onClick={() => setStep((prev) => prev + 1)}
>
Skip
</StyledButton>
</StyledInviteLinkStep>
);
}
+33 -33
View File
@@ -3,42 +3,42 @@ import StyledButton from "../../../common/component/styled/Button";
import PlayIcon from "../../../assets/icons/play.svg?url";
const StyledLastStep = styled.div`
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
> .secondaryText {
margin-bottom: 48px;
}
> .tip {
width: 560px;
font-size: 20px;
line-height: 24px;
text-align: center;
margin-bottom: 96px;
> .strong {
font-weight: 700;
> .secondaryText {
margin-bottom: 48px;
}
> .tip {
width: 560px;
font-size: 20px;
line-height: 24px;
text-align: center;
margin-bottom: 96px;
> .strong {
font-weight: 700;
}
}
}
`;
export default function CompletedStep({ data, setStep }) {
return (
<StyledLastStep>
<span className="primaryText">Welcome to {data.serverName}</span>
<span className="secondaryText">Proudly presented by Rustchat</span>
<span className="tip">
More settings, including domain resolution, privileges, securities, and invites are available in{" "}
<span className="strong">Settings</span>
</span>
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
<img src={PlayIcon} alt="play icon" />
<span>Enter</span>
</StyledButton>
</StyledLastStep>
);
return (
<StyledLastStep>
<span className="primaryText">Welcome to {data.serverName}</span>
<span className="secondaryText">Proudly presented by Rustchat</span>
<span className="tip">
More settings, including domain resolution, privileges, securities, and invites are
available in <span className="strong">Settings</span>
</span>
<StyledButton className="startButton" onClick={() => setStep((prev) => prev + 1)}>
<img src={PlayIcon} alt="play icon" />
<span>Enter</span>
</StyledButton>
</StyledLastStep>
);
}
+63 -63
View File
@@ -1,75 +1,75 @@
import styled from "styled-components";
const StyledOnboardingPage = styled.div`
height: 100vh;
overflow-y: auto;
height: 100vh;
overflow-y: auto;
// shared with child components
.primaryText,
.secondaryText {
text-align: center;
}
.primaryText {
font-weight: 700;
font-size: 24px;
line-height: 30px;
margin-bottom: 8px;
}
.secondaryText {
font-size: 14px;
line-height: 20px;
margin-bottom: 24px;
}
.startButton {
width: 128px;
display: flex;
flex-direction: column;
align-items: center;
padding: 15px 0 12px;
> img {
margin-bottom: 7px;
// shared with child components
.primaryText,
.secondaryText {
text-align: center;
}
> span {
font-weight: 500;
font-size: 14px;
line-height: 20px;
.primaryText {
font-weight: 700;
font-size: 24px;
line-height: 30px;
margin-bottom: 8px;
}
}
.input {
width: 360px;
height: 44px;
border: none;
box-shadow: none;
}
input.input {
font-weight: 400;
font-size: 16px;
line-height: 24px;
padding: 10px 14px;
border: 1px solid #d0d5dd;
border-radius: 8px;
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
}
.button {
width: 360px;
&.ghost.border_less {
width: fit-content;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #98a2b3;
margin-top: 14px;
.secondaryText {
font-size: 14px;
line-height: 20px;
margin-bottom: 24px;
}
.startButton {
width: 128px;
display: flex;
flex-direction: column;
align-items: center;
padding: 15px 0 12px;
> img {
margin-bottom: 7px;
}
> span {
font-weight: 500;
font-size: 14px;
line-height: 20px;
}
}
.input {
width: 360px;
height: 44px;
border: none;
box-shadow: none;
}
input.input {
font-weight: 400;
font-size: 16px;
line-height: 24px;
padding: 10px 14px;
border: 1px solid #d0d5dd;
border-radius: 8px;
box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
}
.button {
width: 360px;
&.ghost.border_less {
width: fit-content;
font-weight: 500;
font-size: 16px;
line-height: 24px;
color: #98a2b3;
margin-top: 14px;
}
}
}
`;
export default StyledOnboardingPage;
+1 -3
View File
@@ -26,9 +26,7 @@ export default function ExpiredTip() {
return (
<Styled>
<div className="title">Magic link expired</div>
<p className="desc">
Go back to your original Rustchat tab and request a new magic link.
</p>
<p className="desc">Go back to your original Rustchat tab and request a new magic link.</p>
<p className="desc">You can close this window now.</p>
</Styled>
);
+6 -11
View File
@@ -8,19 +8,14 @@ import { setAuthData } from "../../app/slices/auth.data";
import Input from "../../common/component/styled/Input";
import Button from "../../common/component/styled/Button";
import {
useLoginMutation,
useCheckInviteTokenValidMutation,
} from "../../app/services/auth";
import { useLoginMutation, useCheckInviteTokenValidMutation } from "../../app/services/auth";
import toast from "react-hot-toast";
import ExpiredTip from "./ExpiredTip";
export default function RegWithUsername() {
const { token } = useParams();
const [
checkTokenInvalid,
{ data: isTokenValid, isLoading: checkingToken },
] = useCheckInviteTokenValidMutation();
const [checkTokenInvalid, { data: isTokenValid, isLoading: checkingToken }] =
useCheckInviteTokenValidMutation();
const [login, { isLoading, error, isSuccess, data }] = useLoginMutation();
// const navigateTo = useNavigate();
const dispatch = useDispatch();
@@ -57,7 +52,7 @@ export default function RegWithUsername() {
login({
token,
username,
type: "magiclink",
type: "magiclink"
});
// sendMagicLink(email);
};
@@ -74,8 +69,8 @@ export default function RegWithUsername() {
<div className="tips">
<h2 className="title">Whats your name</h2>
<span className="desc">
Enter a name or handle so people know how youd like to be called.
Your name will only be visible to others in spaces you joined.
Enter a name or handle so people know how youd like to be called. Your name will only be
visible to others in spaces you joined.
</span>
</div>
<form onSubmit={handleLogin}>
+1 -2
View File
@@ -7,8 +7,7 @@ const StyledWrapper = styled.div`
.form {
max-width: 440px;
padding: 36px 40px 32px 40px;
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1),
0px 2px 4px -2px rgba(16, 24, 40, 0.06);
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
+1 -5
View File
@@ -70,11 +70,7 @@ export default function Channel({ select = "", updateFilter }) {
</li>
{channels.map(({ gid, is_public, name }) => {
return (
<li
key={gid}
className="channel"
onClick={handleClick.bind(null, gid)}
>
<li key={gid} className="channel" onClick={handleClick.bind(null, gid)}>
<ChannelIcon personal={!is_public} />
<span className="name">{name}</span>
{select == gid && <CheckSign className="check" />}
+7 -11
View File
@@ -42,20 +42,20 @@ const Styled = styled.div`
export const Dates = {
today: {
title: "Today",
duration: 2222,
duration: 2222
},
in7d: {
title: "Last 7 Days",
title: "Last 7 Days"
},
in30d: {
title: "Last 30 Days",
title: "Last 30 Days"
},
in3m: {
title: "Last 3 months",
title: "Last 3 months"
},
in12m: {
title: "Last 12 months",
},
title: "Last 12 months"
}
};
export default function Date({ select = "", updateFilter }) {
// const { input, updateInput, contacts } = useFilteredUsers();
@@ -75,11 +75,7 @@ export default function Date({ select = "", updateFilter }) {
</li>
{Object.entries(Dates).map(([_key, { title }]) => {
return (
<li
key={title}
className="date"
onClick={handleClick.bind(null, _key)}
>
<li key={title} className="date" onClick={handleClick.bind(null, _key)}>
{title}
{select == _key && <CheckSign className="check" />}
</li>
+2 -9
View File
@@ -64,20 +64,13 @@ export default function From({ select = "", updateFilter }) {
<Search embed={true} value={input} updateSearchValue={updateInput} />
</div>
<ul className="list">
<li
className="contact none"
onClick={handleClick.bind(null, undefined)}
>
<li className="contact none" onClick={handleClick.bind(null, undefined)}>
Anyone
{!select && <CheckSign className="check" />}
</li>
{contacts.map(({ uid }) => {
return (
<li
key={uid}
className="contact"
onClick={handleClick.bind(null, uid)}
>
<li key={uid} className="contact" onClick={handleClick.bind(null, uid)}>
<Contact uid={uid} interactive={true} />
{select == uid && <CheckSign className="check" />}
</li>
+9 -13
View File
@@ -54,32 +54,32 @@ const Styled = styled.div`
export const FileTypes = {
doc: {
title: "Documents",
icon: <IconDoc className="icon" />,
icon: <IconDoc className="icon" />
},
pdf: {
title: "PDFs",
icon: <IconPdf className="icon" />,
icon: <IconPdf className="icon" />
},
image: {
title: "Images",
icon: <IconImage className="icon" />,
icon: <IconImage className="icon" />
},
audio: {
title: "Audio",
icon: <IconAudio className="icon" />,
icon: <IconAudio className="icon" />
},
video: {
title: "Videos",
icon: <IconVideo className="icon" />,
icon: <IconVideo className="icon" />
},
code: {
title: "Code Snippets",
icon: <IconCode className="icon" />,
icon: <IconCode className="icon" />
},
unkown: {
title: "Unkown Files",
icon: <IconUnkown className="icon" />,
},
icon: <IconUnkown className="icon" />
}
};
export default function Type({ select = "", updateFilter }) {
// const { input, updateInput, contacts } = useFilteredUsers();
@@ -99,11 +99,7 @@ export default function Type({ select = "", updateFilter }) {
</li>
{Object.entries(FileTypes).map(([type, { title, icon }]) => {
return (
<li
key={title}
className="type"
onClick={handleClick.bind(null, type)}
>
<li key={title} className="type" onClick={handleClick.bind(null, type)}>
{icon} {title}
{select == type && <CheckSign className="check" />}
</li>
+9 -26
View File
@@ -47,7 +47,7 @@ export default function Filter({ filter, updateFilter }) {
channel: false,
date: false,
from: false,
type: false,
type: false
});
const toggleFilterVisible = (obj) => {
setFiltersVisible((prev) => {
@@ -58,7 +58,7 @@ export default function Filter({ filter, updateFilter }) {
updateFilter(data);
let _key = Object.keys(data)[0];
let tmp = {
[_key]: false,
[_key]: false
};
console.log("wtffff", tmp);
toggleFilterVisible(tmp);
@@ -72,7 +72,7 @@ export default function Filter({ filter, updateFilter }) {
channel: channelVisible,
date: dateVisible,
type: typeVisible,
from: fromVisible,
from: fromVisible
} = filtersVisible;
return (
<Styled>
@@ -81,20 +81,14 @@ export default function Filter({ filter, updateFilter }) {
onClickOutside={toggleFilterVisible.bind(null, { from: false })}
visible={fromVisible}
placement="bottom-start"
content={
<FilterFrom select={filter.from} updateFilter={handleUpdateFilter} />
}
content={<FilterFrom select={filter.from} updateFilter={handleUpdateFilter} />}
>
<div
className={`filter ${from && "selected"}`}
onClick={toggleFilterVisible.bind(null, { from: true })}
>
{from && (
<Avatar
className="avatar"
name={contactMap[from].name}
url={contactMap[from].avatar}
/>
<Avatar className="avatar" name={contactMap[from].name} url={contactMap[from].avatar} />
)}
<span className="txt">From {from && contactMap[from].name}</span>
<ArrowDown className="arrow" />
@@ -105,20 +99,13 @@ export default function Filter({ filter, updateFilter }) {
onClickOutside={toggleFilterVisible.bind(null, { channel: false })}
visible={channelVisible}
placement="bottom-start"
content={
<FilterChannel
select={filter.channel}
updateFilter={handleUpdateFilter}
/>
}
content={<FilterChannel select={filter.channel} updateFilter={handleUpdateFilter} />}
>
<div
className={`filter ${channel && "selected"}`}
onClick={toggleFilterVisible.bind(null, { channel: true })}
>
<span className="txt">
{channel ? `In ${channelMap[channel].name}` : `Channel`}
</span>
<span className="txt">{channel ? `In ${channelMap[channel].name}` : `Channel`}</span>
<ArrowDown className="arrow" />
</div>
</Tippy>
@@ -127,9 +114,7 @@ export default function Filter({ filter, updateFilter }) {
onClickOutside={toggleFilterVisible.bind(null, { type: false })}
visible={typeVisible}
placement="bottom-start"
content={
<FilterType select={filter.type} updateFilter={handleUpdateFilter} />
}
content={<FilterType select={filter.type} updateFilter={handleUpdateFilter} />}
>
<div
className={`filter ${type && "selected"}`}
@@ -144,9 +129,7 @@ export default function Filter({ filter, updateFilter }) {
onClickOutside={toggleFilterVisible.bind(null, { date: false })}
visible={dateVisible}
placement="bottom-start"
content={
<FilterDate select={filter.date} updateFilter={handleUpdateFilter} />
}
content={<FilterDate select={filter.date} updateFilter={handleUpdateFilter} />}
>
<div
className={`filter ${date && "selected"}`}
+2 -11
View File
@@ -23,11 +23,7 @@ const Styled = styled.div`
background-position: 8px center;
}
`;
export default function Search({
value = "",
updateSearchValue = null,
embed = false,
}) {
export default function Search({ value = "", updateSearchValue = null, embed = false }) {
const handleChange = (evt) => {
if (updateSearchValue) {
updateSearchValue(evt.target.value);
@@ -35,12 +31,7 @@ export default function Search({
};
return (
<Styled className={embed ? "embed" : ""}>
<input
value={value}
onChange={handleChange}
className="search"
placeholder="Search..."
/>
<input value={value} onChange={handleChange} className="search" placeholder="Search..." />
</Styled>
);
}
+2 -10
View File
@@ -43,18 +43,10 @@ export default function View({ view = Views.item }) {
};
return (
<Styled className={view}>
<li
className="view item"
data-view={Views.item}
onClick={handleChangeView}
>
<li className="view item" data-view={Views.item} onClick={handleChangeView}>
<IconList />
</li>
<li
className="view grid"
data-view={Views.grid}
onClick={handleChangeView}
>
<li className="view grid" data-view={Views.grid} onClick={handleChangeView}>
<IconGrid />
</li>
</Styled>
+4 -7
View File
@@ -17,16 +17,13 @@ const checkFilter = (data, filter, channelMessage) => {
type: typeFilter,
date: timeFilter,
from: fromFilter,
channel: channelFilter,
channel: channelFilter
} = filter;
const name = properties ? properties.name : "";
if (fromFilter && fromFilter != from_uid) {
selected = false;
}
if (
channelFilter &&
channelMessage[channelFilter].findIndex((id) => id == mid) == -1
) {
if (channelFilter && channelMessage[channelFilter].findIndex((id) => id == mid) == -1) {
selected = false;
}
if (nameFilter) {
@@ -46,7 +43,7 @@ function ResourceManagement({ fileMessages }) {
return {
message: store.message,
channelMessage: store.channelMessage,
view: store.ui.fileListView,
view: store.ui.fileListView
};
});
@@ -72,7 +69,7 @@ function ResourceManagement({ fileMessages }) {
// options
fitWidth: true,
gutter,
itemSelector: ".file_box",
itemSelector: ".file_box"
// columnWidth: 200
});
} else {
+2 -9
View File
@@ -12,10 +12,7 @@ import SentTip from "./SentTip";
export default function SendMagicLinkPage() {
const [sent, setSent] = useState(false);
const [
sendMagicLink,
{ isSuccess, isLoading, error },
] = useSendMagicLinkMutation();
const [sendMagicLink, { isSuccess, isLoading, error }] = useSendMagicLinkMutation();
const navigateTo = useNavigate();
// const dispatch = useDispatch();
@@ -73,11 +70,7 @@ export default function SendMagicLinkPage() {
) : (
<>
<div className="tips">
<img
src={`${BASE_URL}/resource/organization/logo`}
alt="logo"
className="logo"
/>
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
<h2 className="title">Login to Rustchat</h2>
<span className="desc">Please enter your Email</span>
</div>
+1 -2
View File
@@ -8,8 +8,7 @@ const StyledWrapper = styled.div`
max-width: 440px;
padding: 32px 40px 32px 40px;
/* border: 1px solid #eee; */
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1),
0px 2px 4px -2px rgba(16, 24, 40, 0.06);
box-shadow: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 12px;
.tips {
display: flex;
+7 -14
View File
@@ -52,16 +52,14 @@ import Input from "../../common/component/styled/Input";
import Button from "../../common/component/styled/Button";
import {
useGetThirdPartySecretQuery,
useUpdateThirdPartySecretMutation,
useUpdateThirdPartySecretMutation
} from "../../app/services/server";
import Tippy from "@tippyjs/react";
import toast from "react-hot-toast";
export default function APIConfig() {
const { data } = useGetThirdPartySecretQuery();
const [
updateSecret,
{ data: updatedSecret, isSuccess, isLoading },
] = useUpdateThirdPartySecretMutation();
const [updateSecret, { data: updatedSecret, isSuccess, isLoading }] =
useUpdateThirdPartySecretMutation();
console.log("secret", data);
useEffect(() => {
if (isSuccess) {
@@ -83,18 +81,13 @@ export default function APIConfig() {
content={
<StyledConfirm>
<div className="tip">
Are you sure to update API secret? Previous secret will be
invalided
Are you sure to update API secret? Previous secret will be invalided
</div>
<div className="btns">
<Button onClick={hideAll} className="cancel small">
Cancel
</Button>
<Button
disabled={isLoading}
className="small danger"
onClick={updateSecret}
>
<Button disabled={isLoading} className="small danger" onClick={updateSecret}>
Yes
</Button>
</div>
@@ -104,8 +97,8 @@ export default function APIConfig() {
<Button>Update Secret</Button>
</Tippy>
<div className="tip">
Tip: The security key agreed between the rustchat server and the
third-party app is used to encrypt the communication data.{" "}
Tip: The security key agreed between the rustchat server and the third-party app is used to
encrypt the communication data.{" "}
</div>
</Styled>
);
+1 -5
View File
@@ -69,11 +69,7 @@ export default function LogoutConfirmModal({ closeModal }) {
<label htmlFor="clear_cb" className="txt">
Clear local data
</label>
<Checkbox
name="clear_cb"
checked={clearLocal}
onChange={handleCheck}
/>
<Checkbox name="clear_cb" checked={clearLocal} onChange={handleCheck} />
</div>
</StyledConfirm>
</Modal>
+6 -12
View File
@@ -101,21 +101,18 @@ const EditModalInfo = {
name: {
label: "Username",
title: "Change your username",
intro: "Enter a new username.",
intro: "Enter a new username."
},
email: {
label: "Email",
title: "Change your email",
intro: "Enter a new email.",
},
intro: "Enter a new email."
}
};
export default function MyAccount() {
const [passwordModal, setPasswordModal] = useState(false);
const [editModal, setEditModal] = useState(null);
const [
uploadAvatar,
{ isSuccess: uploadSuccess },
] = useUpdateAvatarMutation();
const [uploadAvatar, { isSuccess: uploadSuccess }] = useUpdateAvatarMutation();
const loginUser = useSelector((store) => {
return store.contacts.byId[store.authData.uid];
});
@@ -177,8 +174,7 @@ export default function MyAccount() {
<div className="danger">
<h4 className="head">Account Removal</h4>
<div className="desc">
Disabling your account means you can recover it at any time after
taking this action.
Disabling your account means you can recover it at any time after taking this action.
</div>
<button className="btn">Delete Account</button>
</div>
@@ -191,9 +187,7 @@ export default function MyAccount() {
closeModal={closeBasicEditModal}
/>
)}
{passwordModal && (
<UpdatePasswordModal closeModal={togglePasswordModal} />
)}
{passwordModal && <UpdatePasswordModal closeModal={togglePasswordModal} />}
</>
);
}
+1 -4
View File
@@ -17,10 +17,7 @@ export default function Notifications() {
return (
<StyledWrapper>
<Label>Notification Setting:</Label>
<StyledToggle
data-checked={status == "granted"}
onClick={handleEnableNotify}
/>
<StyledToggle data-checked={status == "granted"} onClick={handleEnableNotify} />
</StyledWrapper>
);
}
+4 -6
View File
@@ -4,7 +4,7 @@ import { useSelector } from "react-redux";
import {
useGetServerQuery,
useUpdateServerMutation,
useUpdateLogoMutation,
useUpdateLogoMutation
} from "../../app/services/server";
import LogoUploader from "../../common/component/AvatarUploader";
import Input from "../../common/component/styled/Input";
@@ -136,8 +136,8 @@ export default function Overview() {
{isAdmin && (
<div className="upload">
<div className="tip">
Minimum size is 128x128, We recommend at least 512x512 for the
server. Max size limited to 5M.
Minimum size is 128x128, We recommend at least 512x512 for the server. Max size
limited to 5M.
</div>
{/* <button className="btn">Upload Image</button> */}
</div>
@@ -170,9 +170,7 @@ export default function Overview() {
/>
</div>
</div>
{changed && (
<SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />
)}
{changed && <SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />}
{/* <button onClick={handleUpdate} className="btn">update</button> */}
</StyledWrapper>
);
+2 -4
View File
@@ -28,7 +28,7 @@ export default function ProfileBasicEditModal({
value = "",
title = "Change your username",
intro = "Enter a new username and your existing password.",
closeModal,
closeModal
}) {
const [input, setInput] = useState(value);
// const dispatch = useDispatch();
@@ -56,9 +56,7 @@ export default function ProfileBasicEditModal({
<Button className="cancel" onClick={closeModal}>
Cancel
</Button>
<Button onClick={handleUpdate}>
{isLoading ? "Updating" : `Done`}
</Button>
<Button onClick={handleUpdate}>{isLoading ? "Updating" : `Done`}</Button>
</>
}
>
+3 -9
View File
@@ -2,10 +2,7 @@
import { useEffect, useState } from "react";
import styled from "styled-components";
import Input from "../../common/component/styled/Input";
import {
useUpdatePasswordMutation,
useGetCredentialsQuery,
} from "../../app/services/auth";
import { useUpdatePasswordMutation, useGetCredentialsQuery } from "../../app/services/auth";
import StyledModal from "../../common/component/styled/Modal";
import Button from "../../common/component/styled/Button";
const StyledEdit = styled(StyledModal)`
@@ -30,13 +27,10 @@ export default function ProfileBasicEditModal({ closeModal }) {
const [input, setInput] = useState({
current: "",
newPassword: "",
confirmPassword: "",
confirmPassword: ""
});
// const dispatch = useDispatch();
const [
updatePassword,
{ isLoading, isSuccess },
] = useUpdatePasswordMutation();
const [updatePassword, { isLoading, isSuccess }] = useUpdatePasswordMutation();
const handleChange = (evt) => {
const { type } = evt.target.dataset;
setInput((prev) => {
+2 -9
View File
@@ -7,14 +7,7 @@ import Toggle from "../../../common/component/styled/Toggle";
import SaveTip from "../../../common/component/SaveTip";
import useConfig from "../../../common/hook/useConfig";
export default function ConfigAgora() {
const {
changed,
reset,
values,
setValues,
toggleEnable,
updateConfig,
} = useConfig("agora");
const { changed, reset, values, setValues, toggleEnable, updateConfig } = useConfig("agora");
const handleUpdate = () => {
// const { token_url, description } = values;
updateConfig(values);
@@ -34,7 +27,7 @@ export default function ConfigAgora() {
app_certificate,
rtm_key,
rtm_secret,
enabled = false,
enabled = false
} = values ?? {};
return (
<StyledContainer>
+2 -10
View File
@@ -8,14 +8,7 @@ import SaveTip from "../../../common/component/SaveTip";
import useConfig from "../../../common/hook/useConfig";
export default function ConfigFirebase() {
const {
values,
toggleEnable,
updateConfig,
setValues,
reset,
changed,
} = useConfig("firebase");
const { values, toggleEnable, updateConfig, setValues, reset, changed } = useConfig("firebase");
const handleUpdate = () => {
// const { token_url, description } = values;
updateConfig(values);
@@ -28,8 +21,7 @@ export default function ConfigFirebase() {
});
};
// if (!values) return null;
const { token_url, project_id, private_key, client_email, enabled = false } =
values ?? {};
const { token_url, project_id, private_key, client_email, enabled = false } = values ?? {};
return (
<StyledContainer>
<div className="inputs">
+6 -13
View File
@@ -15,17 +15,15 @@ export default function Logins() {
changed: clientIdChanged,
clientId,
updateClientId,
updateClientIdToServer,
updateClientIdToServer
} = useGoogleAuthConfig();
const {
config: githubAuthConfig,
changed: githubChanged,
updateGithubAuthConfigToServer,
updateGithubAuthConfig,
updateGithubAuthConfig
} = useGithubAuthConfig();
const { values, updateConfig, setValues, reset, changed } = useConfig(
"login"
);
const { values, updateConfig, setValues, reset, changed } = useConfig("login");
const handleUpdate = async () => {
const { google } = values;
if (changed) {
@@ -70,8 +68,7 @@ export default function Logins() {
});
};
if (!values) return null;
const { google, magic_link, github, metamask, password, oidc = [] } =
values ?? {};
const { google, magic_link, github, metamask, password, oidc = [] } = values ?? {};
const valuesChanged = clientIdChanged || changed || githubChanged;
return (
@@ -97,9 +94,7 @@ export default function Logins() {
<div className="txt">
<Label>Magic Link</Label>
</div>
<span className="desc">
Allows members login with Magic Link.
</span>
<span className="desc">Allows members login with Magic Link.</span>
</div>
<Toggle
onClick={handleToggle.bind(null, { magic_link: !magic_link })}
@@ -191,9 +186,7 @@ export default function Logins() {
</div>
</div>
</div>
{valuesChanged && (
<SaveTip saveHandler={handleUpdate} resetHandler={reset} />
)}
{valuesChanged && <SaveTip saveHandler={handleUpdate} resetHandler={reset} />}
</StyledContainer>
);
}
+3 -11
View File
@@ -20,14 +20,7 @@ import toast from "react-hot-toast";
export default function ConfigSMTP() {
const [testEmail, setTestEmail] = useState("");
const [sendTestEmail, { isSuccess, isError }] = useSendTestEmailMutation();
const {
reset,
updateConfig,
values,
setValues,
changed,
toggleEnable,
} = useConfig("smtp");
const { reset, updateConfig, values, setValues, changed, toggleEnable } = useConfig("smtp");
const handleUpdate = () => {
// const { token_url, description } = values;
@@ -49,7 +42,7 @@ export default function ConfigSMTP() {
sendTestEmail({
to: testEmail,
subject: "test title",
content: "test content",
content: "test content"
});
};
useEffect(() => {
@@ -62,8 +55,7 @@ export default function ConfigSMTP() {
}, [isSuccess, isError]);
// if (!values) return null;
const { host, port, from, username, password, enabled = false } =
values ?? {};
const { host, port, from, username, password, enabled = false } = values ?? {};
console.log("values", values);
return (
<StyledContainer>
+20 -20
View File
@@ -16,20 +16,20 @@ const navs = [
{
name: "overview",
title: "Overview",
component: <Overview />,
component: <Overview />
},
{
name: "members",
title: "Members",
component: <ManageMembers />,
admin: true,
},
admin: true
}
// {
// name: "notification",
// title: "Notification",
// component: <Notifications />,
// },
],
]
},
{
title: "User",
@@ -37,9 +37,9 @@ const navs = [
{
name: "my_account",
title: "My Account",
component: <MyAccount />,
},
],
component: <MyAccount />
}
]
},
{
title: "Configuration",
@@ -47,30 +47,30 @@ const navs = [
{
name: "firebase",
title: "Firebase",
component: <ConfigFirebase />,
component: <ConfigFirebase />
},
{
name: "agora",
title: "Agora",
component: <ConfigAgora />,
component: <ConfigAgora />
},
{
name: "smtp",
title: "SMTP",
component: <ConfigSMTP />,
component: <ConfigSMTP />
},
{
name: "social_login",
title: "Login Methods",
component: <Logins />,
component: <Logins />
},
{
name: "api",
title: "Third-party APP",
component: <APIConfig />,
},
component: <APIConfig />
}
],
admin: true,
admin: true
},
{
title: "About",
@@ -78,20 +78,20 @@ const navs = [
{
name: "faq",
title: "FAQ",
component: <FAQ />,
component: <FAQ />
},
{
name: "terms",
title: "Terms & Privacy",
component: "Terms & Privacy",
component: "Terms & Privacy"
},
{
name: "feedback",
title: "Feedback",
component: "feedback",
},
],
},
component: "feedback"
}
]
}
];
const useNavs = () => {
const loginUser = useSelector((store) => {
@@ -30,10 +30,7 @@ export default function DeleteConfirmModal({ id, closeModal }) {
description="Are you sure want to delete this channel?"
buttons={
<>
<Button
onClick={closeModal.bind(null, undefined)}
className="cancel"
>
<Button onClick={closeModal.bind(null, undefined)} className="cancel">
Cancel
</Button>
<Button onClick={handleDelete} className="danger">
+4 -11
View File
@@ -4,7 +4,7 @@ import toast from "react-hot-toast";
import {
useGetChannelQuery,
useUpdateChannelMutation,
useUpdateIconMutation,
useUpdateIconMutation
} from "../../app/services/channel";
import AvatarUploader from "../../common/component/AvatarUploader";
import Input from "../../common/component/styled/Input";
@@ -46,7 +46,7 @@ export default function Overview({ id = 0 }) {
const { loginUser, channel } = useSelector((store) => {
return {
loginUser: store.contacts.byId[store.authData.uid],
channel: store.channels.byId[id],
channel: store.channels.byId[id]
};
});
const { data, refetch } = useGetChannelQuery(id);
@@ -102,12 +102,7 @@ export default function Overview({ id = 0 }) {
console.log("channel icon", channel);
return (
<StyledWrapper>
<AvatarUploader
type="channel"
url={channel?.icon}
name={name}
uploadImage={updateIcon}
/>
<AvatarUploader type="channel" url={channel?.icon} name={name} uploadImage={updateIcon} />
<div className="inputs">
<div className="input">
<Label htmlFor="name">Channel Name</Label>
@@ -136,9 +131,7 @@ export default function Overview({ id = 0 }) {
/>
</div>
</div>
{changed && (
<SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />
)}
{changed && <SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />}
{/* <button onClick={handleUpdate} className="btn">update</button> */}
</StyledWrapper>
);
+6 -10
View File
@@ -12,7 +12,7 @@ export default function ChannelSetting() {
return {
loginUid: store.authData.uid,
isAdmin: store.contacts.byId[store.authData.uid]?.is_admin,
channel: store.channels.byId[cid],
channel: store.channels.byId[cid]
};
});
const navigate = useNavigate();
@@ -52,22 +52,18 @@ export default function ChannelSetting() {
dangers={[
canLeave && {
title: "Leave Channel",
handler: toggleLeaveConfrim,
handler: toggleLeaveConfrim
},
canDelete && {
title: "Delete Channel",
handler: toggleDeleteConfrim,
},
handler: toggleDeleteConfrim
}
]}
>
{currNav.component}
</StyledSettingContainer>
{deleteConfirm && (
<DeleteConfirmModal closeModal={toggleDeleteConfrim} id={cid} />
)}
{leaveConfirm && (
<LeaveChannel closeModal={toggleLeaveConfrim} id={cid} />
)}
{deleteConfirm && <DeleteConfirmModal closeModal={toggleDeleteConfrim} id={cid} />}
{leaveConfirm && <LeaveChannel closeModal={toggleLeaveConfrim} id={cid} />}
</>
);
}
+5 -5
View File
@@ -8,13 +8,13 @@ const useNavs = (channelId) => {
{
name: "overview",
title: "Overview",
component: <Overview id={channelId} />,
component: <Overview id={channelId} />
},
{
name: "members",
title: "Members",
component: <ManageMembers cid={channelId} />,
},
component: <ManageMembers cid={channelId} />
}
// {
// name: "permissions",
// title: "Permissions",
@@ -27,8 +27,8 @@ const useNavs = (channelId) => {
// name: "integrations",
// title: "Integrations",
// },
],
},
]
}
// {
// title: "User Management",
// items: [