refactor: favorite error tip
This commit is contained in:
@@ -69,9 +69,9 @@ export default function Commands({
|
|||||||
from_uid = 0,
|
from_uid = 0,
|
||||||
toggleEditMessage,
|
toggleEditMessage,
|
||||||
}) {
|
}) {
|
||||||
const { addFavorite, isFavorited } = useFavMessage(
|
const { addFavorite, isFavorited } = useFavMessage({
|
||||||
context == "channel" ? contextId : null
|
cid: context == "channel" ? contextId : null,
|
||||||
);
|
});
|
||||||
const [mids, setMids] = useState([]);
|
const [mids, setMids] = useState([]);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [pinModalVisible, setPinModalVisible] = useState(false);
|
const [pinModalVisible, setPinModalVisible] = useState(false);
|
||||||
@@ -122,8 +122,12 @@ export default function Commands({
|
|||||||
toast.success("Favorited!");
|
toast.success("Favorited!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await addFavorite(mid);
|
const added = await addFavorite(mid);
|
||||||
toast.success("Added Favorites!");
|
if (added) {
|
||||||
|
toast.success("Added Favorites!");
|
||||||
|
} else {
|
||||||
|
toast.error("Added Favorites Failed!");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isUnpinSuccess) {
|
if (isUnpinSuccess) {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const StyledSaved = styled.div`
|
|||||||
padding: 8px;
|
padding: 8px;
|
||||||
`;
|
`;
|
||||||
const SavedMessage = ({ cid, id }) => {
|
const SavedMessage = ({ cid, id }) => {
|
||||||
const { favorites } = useFavMessage(cid);
|
const { favorites } = useFavMessage({ cid });
|
||||||
const [fav, setFav] = useState(null);
|
const [fav, setFav] = useState(null);
|
||||||
const [messages, setMessages] = useState(null);
|
const [messages, setMessages] = useState(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -4,21 +4,20 @@ import {
|
|||||||
useLazyRemoveFavoriteQuery,
|
useLazyRemoveFavoriteQuery,
|
||||||
useFavoriteMessageMutation,
|
useFavoriteMessageMutation,
|
||||||
} from "../../app/services/message";
|
} from "../../app/services/message";
|
||||||
export default function useFavMessage(cid = null) {
|
export default function useFavMessage({ cid = null, uid = null }) {
|
||||||
const [removeFav] = useLazyRemoveFavoriteQuery();
|
const [removeFav] = useLazyRemoveFavoriteQuery();
|
||||||
const [addFav] = useFavoriteMessageMutation();
|
const [addFav] = useFavoriteMessageMutation();
|
||||||
const [favorites, setFavorites] = useState([]);
|
const [favorites, setFavorites] = useState([]);
|
||||||
const { favs = [] } = useSelector((store) => {
|
const { favs = [] } = useSelector((store) => {
|
||||||
return {
|
return {
|
||||||
// mids: store.channelMessage.byId[cid],
|
|
||||||
favs: store.favorites,
|
favs: store.favorites,
|
||||||
// loginUser: store.contacts.byId[store.authData.uid],
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const addFavorite = async (mid = []) => {
|
const addFavorite = async (mid = []) => {
|
||||||
const mids = Array.isArray(mid) ? mid.map((i) => +i) : [+mid];
|
const mids = Array.isArray(mid) ? mid.map((i) => +i) : [+mid];
|
||||||
if (mids.length == 0) return;
|
if (mids.length == 0) return;
|
||||||
await addFav(mids);
|
const { error = null } = await addFav(mids);
|
||||||
|
return !error;
|
||||||
};
|
};
|
||||||
const removeFavorite = (id) => {
|
const removeFavorite = (id) => {
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
@@ -36,16 +35,23 @@ export default function useFavMessage(cid = null) {
|
|||||||
return mids.findIndex((i) => i == mid) > -1;
|
return mids.findIndex((i) => i == mid) > -1;
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filtereds = cid
|
let filtereds = [];
|
||||||
|
filtereds = cid
|
||||||
? favs.filter((f) => {
|
? favs.filter((f) => {
|
||||||
if (!f.messages) return false;
|
if (!f.messages) return false;
|
||||||
return f.messages.every((m) => m.source.gid == cid);
|
return f.messages.every((m) => m.source.gid == cid);
|
||||||
})
|
})
|
||||||
: favs;
|
: favs;
|
||||||
console.log("filtered", filtereds);
|
filtereds = uid
|
||||||
setFavorites(filtereds);
|
? filtereds.filter((f) => {
|
||||||
}, [cid, favs]);
|
if (!f.messages) return false;
|
||||||
|
return f.messages.every((m) => m.source.uid == uid);
|
||||||
|
})
|
||||||
|
: filtereds;
|
||||||
|
|
||||||
|
setFavorites(filtereds);
|
||||||
|
}, [cid, uid, favs]);
|
||||||
|
console.log("filtered", cid, uid, favs);
|
||||||
return {
|
return {
|
||||||
isFavorited,
|
isFavorited,
|
||||||
addFavorite,
|
addFavorite,
|
||||||
|
|||||||
@@ -1,231 +1,259 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from "react";
|
||||||
import { useDebounce } from 'rooks';
|
import { useDebounce } from "rooks";
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from "react-redux";
|
||||||
import PinList from './PinList';
|
import PinList from "./PinList";
|
||||||
import FavList from './FavList';
|
import FavList from "../FavList";
|
||||||
import { useReadMessageMutation } from '../../../app/services/message';
|
import { useReadMessageMutation } from "../../../app/services/message";
|
||||||
import useChatScroll from '../../../common/hook/useChatScroll';
|
import useChatScroll from "../../../common/hook/useChatScroll";
|
||||||
import ChannelIcon from '../../../common/component/ChannelIcon';
|
import ChannelIcon from "../../../common/component/ChannelIcon";
|
||||||
import Tooltip from '../../../common/component/Tooltip';
|
import Tooltip from "../../../common/component/Tooltip";
|
||||||
import Contact from '../../../common/component/Contact';
|
import Contact from "../../../common/component/Contact";
|
||||||
import Layout from '../Layout';
|
import Layout from "../Layout";
|
||||||
import { renderMessageFragment } from '../utils';
|
import { renderMessageFragment } from "../utils";
|
||||||
import EditIcon from '../../../assets/icons/edit.svg';
|
import EditIcon from "../../../assets/icons/edit.svg";
|
||||||
// import alertIcon from "../../../assets/icons/alert.svg?url";
|
// import alertIcon from "../../../assets/icons/alert.svg?url";
|
||||||
import IconFav from '../../../assets/icons/bookmark.svg';
|
import IconFav from "../../../assets/icons/bookmark.svg";
|
||||||
import IconPeople from '../../../assets/icons/people.svg';
|
import IconPeople from "../../../assets/icons/people.svg";
|
||||||
import IconPin from '../../../assets/icons/pin.svg';
|
import IconPin from "../../../assets/icons/pin.svg";
|
||||||
// import searchIcon from "../../../assets/icons/search.svg?url";
|
// import searchIcon from "../../../assets/icons/search.svg?url";
|
||||||
import IconHeadphone from '../../../assets/icons/headphone.svg';
|
import IconHeadphone from "../../../assets/icons/headphone.svg";
|
||||||
import boardosIcon from '../../../assets/icons/app.boardos.svg?url';
|
import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
|
||||||
import webrowseIcon from '../../../assets/icons/app.webrowse.svg?url';
|
import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
|
||||||
import addIcon from '../../../assets/icons/add.svg?url';
|
import addIcon from "../../../assets/icons/add.svg?url";
|
||||||
import {
|
import {
|
||||||
// StyledNotification,
|
// StyledNotification,
|
||||||
StyledContacts,
|
StyledContacts,
|
||||||
StyledChannelChat,
|
StyledChannelChat,
|
||||||
StyledHeader
|
StyledHeader,
|
||||||
} from './styled';
|
} from "./styled";
|
||||||
import ChannelInviteModal from '../../../common/component/ChannelInviteModal';
|
import ChannelInviteModal from "../../../common/component/ChannelInviteModal";
|
||||||
import { NavLink, useLocation } from 'react-router-dom';
|
import { NavLink, useLocation } from "react-router-dom";
|
||||||
import Tippy from '@tippyjs/react';
|
import Tippy from "@tippyjs/react";
|
||||||
|
|
||||||
export default function ChannelChat({ cid = '', dropFiles = [] }) {
|
export default function ChannelChat({ cid = "", dropFiles = [] }) {
|
||||||
const [toolVisible, setToolVisible] = useState('');
|
const [toolVisible, setToolVisible] = useState("");
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const [updateReadIndex] = useReadMessageMutation();
|
const [updateReadIndex] = useReadMessageMutation();
|
||||||
const updateReadDebounced = useDebounce(updateReadIndex, 300);
|
const updateReadDebounced = useDebounce(updateReadIndex, 300);
|
||||||
const [membersVisible, setMembersVisible] = useState(true);
|
const [membersVisible, setMembersVisible] = useState(true);
|
||||||
const [addMemberModalVisible, setAddMemberModalVisible] = useState(false);
|
const [addMemberModalVisible, setAddMemberModalVisible] = useState(false);
|
||||||
// const dispatch = useDispatch();
|
// const dispatch = useDispatch();
|
||||||
const { selects, msgIds, userIds, data, messageData, loginUid, loginUser, footprint } =
|
const {
|
||||||
useSelector((store) => {
|
selects,
|
||||||
return {
|
msgIds,
|
||||||
selects: store.ui.selectMessages[`channel_${cid}`],
|
userIds,
|
||||||
footprint: store.footprint,
|
data,
|
||||||
loginUser: store.contacts.byId[store.authData.uid],
|
messageData,
|
||||||
loginUid: store.authData.uid,
|
loginUid,
|
||||||
msgIds: store.channelMessage[cid] || [],
|
loginUser,
|
||||||
userIds: store.contacts.ids,
|
footprint,
|
||||||
data: store.channels.byId[cid] || {},
|
} = useSelector((store) => {
|
||||||
messageData: store.message || {}
|
return {
|
||||||
};
|
selects: store.ui.selectMessages[`channel_${cid}`],
|
||||||
|
footprint: store.footprint,
|
||||||
|
loginUser: store.contacts.byId[store.authData.uid],
|
||||||
|
loginUid: store.authData.uid,
|
||||||
|
msgIds: store.channelMessage[cid] || [],
|
||||||
|
userIds: store.contacts.ids,
|
||||||
|
data: store.channels.byId[cid] || {},
|
||||||
|
messageData: store.message || {},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
const ref = useChatScroll(msgIds);
|
const ref = useChatScroll(msgIds);
|
||||||
// const handleClearUnreads = () => {
|
// const handleClearUnreads = () => {
|
||||||
// dispatch(readMessage(msgIds));
|
// dispatch(readMessage(msgIds));
|
||||||
// };
|
// };
|
||||||
const toggleMembersVisible = () => {
|
const toggleMembersVisible = () => {
|
||||||
setMembersVisible((prev) => !prev);
|
setMembersVisible((prev) => !prev);
|
||||||
};
|
};
|
||||||
const toggleAddVisible = () => {
|
const toggleAddVisible = () => {
|
||||||
setAddMemberModalVisible((prev) => !prev);
|
setAddMemberModalVisible((prev) => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { name, description, is_public, members = [], owner } = data;
|
const { name, description, is_public, members = [], owner } = data;
|
||||||
const memberIds = is_public ? userIds : members;
|
const memberIds = is_public ? userIds : members;
|
||||||
const addVisible = loginUser?.is_admin || owner == loginUid;
|
const addVisible = loginUser?.is_admin || owner == loginUid;
|
||||||
console.log('channel message list', msgIds);
|
console.log("channel message list", msgIds);
|
||||||
const readIndex = footprint.readChannels[cid];
|
const readIndex = footprint.readChannels[cid];
|
||||||
const pinCount = data?.pinned_messages?.length || 0;
|
const pinCount = data?.pinned_messages?.length || 0;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{addMemberModalVisible && <ChannelInviteModal cid={cid} closeModal={toggleAddVisible} />}
|
{addMemberModalVisible && (
|
||||||
<Layout
|
<ChannelInviteModal cid={cid} closeModal={toggleAddVisible} />
|
||||||
to={cid}
|
)}
|
||||||
context="channel"
|
<Layout
|
||||||
dropFiles={dropFiles}
|
to={cid}
|
||||||
// ref={containerRef}
|
context="channel"
|
||||||
aside={
|
dropFiles={dropFiles}
|
||||||
<>
|
// ref={containerRef}
|
||||||
<ul className="tools">
|
aside={
|
||||||
{/* <li className="tool">
|
<>
|
||||||
|
<ul className="tools">
|
||||||
|
{/* <li className="tool">
|
||||||
<Tooltip tip="Search" placement="left">
|
<Tooltip tip="Search" placement="left">
|
||||||
<img src={searchIcon} alt="opt icon" />
|
<img src={searchIcon} alt="opt icon" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</li> */}
|
</li> */}
|
||||||
<li className="tool">
|
<li className="tool">
|
||||||
<Tooltip tip="Voice/Video Chat" placement="left">
|
<Tooltip tip="Voice/Video Chat" placement="left">
|
||||||
<IconHeadphone />
|
<IconHeadphone />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</li>
|
</li>
|
||||||
{/* <li className="tool">
|
{/* <li className="tool">
|
||||||
<Tooltip tip="Notifications" placement="left">
|
<Tooltip tip="Notifications" placement="left">
|
||||||
<img src={alertIcon} alt="opt icon" />
|
<img src={alertIcon} alt="opt icon" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</li> */}
|
</li> */}
|
||||||
<Tooltip tip="Pin" placement="left" disabled={toolVisible == 'pin'}>
|
<Tooltip
|
||||||
<Tippy
|
tip="Pin"
|
||||||
onShow={() => {
|
placement="left"
|
||||||
setToolVisible('pin');
|
disabled={toolVisible == "pin"}
|
||||||
}}
|
>
|
||||||
onHide={() => {
|
<Tippy
|
||||||
setToolVisible('');
|
onShow={() => {
|
||||||
}}
|
setToolVisible("pin");
|
||||||
delay={[0, 0]}
|
}}
|
||||||
duration={0}
|
onHide={() => {
|
||||||
placement="left-start"
|
setToolVisible("");
|
||||||
popperOptions={{ strategy: 'fixed' }}
|
}}
|
||||||
offset={[0, 80]}
|
delay={[0, 0]}
|
||||||
interactive
|
duration={0}
|
||||||
trigger="click"
|
placement="left-start"
|
||||||
content={<PinList id={cid} />}
|
popperOptions={{ strategy: "fixed" }}
|
||||||
>
|
offset={[0, 80]}
|
||||||
<li
|
interactive
|
||||||
className={`tool ${pinCount > 0 ? 'badge' : ''} ${toolVisible == 'pin' ? 'active' : ''} `}
|
trigger="click"
|
||||||
data-count={pinCount}
|
content={<PinList id={cid} />}
|
||||||
>
|
>
|
||||||
<IconPin />
|
<li
|
||||||
</li>
|
className={`tool ${pinCount > 0 ? "badge" : ""} ${
|
||||||
</Tippy>
|
toolVisible == "pin" ? "active" : ""
|
||||||
</Tooltip>
|
} `}
|
||||||
<Tooltip tip="Favorite" placement="left" disabled={toolVisible == 'favorite'}>
|
data-count={pinCount}
|
||||||
<Tippy
|
>
|
||||||
onShow={() => {
|
<IconPin />
|
||||||
setToolVisible('favorite');
|
</li>
|
||||||
}}
|
</Tippy>
|
||||||
onHide={() => {
|
</Tooltip>
|
||||||
setToolVisible('');
|
<Tooltip
|
||||||
}}
|
tip="Favorite"
|
||||||
delay={[0, 0]}
|
placement="left"
|
||||||
duration={0}
|
disabled={toolVisible == "favorite"}
|
||||||
placement="left-start"
|
>
|
||||||
popperOptions={{ strategy: 'fixed' }}
|
<Tippy
|
||||||
offset={[0, 180]}
|
onShow={() => {
|
||||||
interactive
|
setToolVisible("favorite");
|
||||||
trigger="click"
|
}}
|
||||||
content={<FavList cid={cid} />}
|
onHide={() => {
|
||||||
>
|
setToolVisible("");
|
||||||
<li
|
}}
|
||||||
className={`tool fav ${toolVisible == 'favorite' ? 'active' : ''} `}
|
delay={[0, 0]}
|
||||||
data-count={pinCount}
|
duration={0}
|
||||||
>
|
placement="left-start"
|
||||||
<IconFav />
|
popperOptions={{ strategy: "fixed" }}
|
||||||
</li>
|
offset={[0, 180]}
|
||||||
</Tippy>
|
interactive
|
||||||
</Tooltip>
|
trigger="click"
|
||||||
<li className={`tool ${membersVisible ? 'active' : ''}`} onClick={toggleMembersVisible}>
|
content={<FavList cid={cid} />}
|
||||||
<Tooltip tip="Channel Members" placement="left">
|
>
|
||||||
<IconPeople />
|
<li
|
||||||
</Tooltip>
|
className={`tool fav ${
|
||||||
</li>
|
toolVisible == "favorite" ? "active" : ""
|
||||||
</ul>
|
} `}
|
||||||
<hr className="divider" />
|
data-count={pinCount}
|
||||||
<ul className="apps">
|
>
|
||||||
<li className="app">
|
<IconFav />
|
||||||
<Tooltip tip="Webrowse" placement="left">
|
</li>
|
||||||
<img src={webrowseIcon} alt="app icon" />
|
</Tippy>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</li>
|
<li
|
||||||
<li className="app">
|
className={`tool ${membersVisible ? "active" : ""}`}
|
||||||
<Tooltip tip="BoardOS" placement="left">
|
onClick={toggleMembersVisible}
|
||||||
<img src={boardosIcon} alt="app icon" />
|
>
|
||||||
</Tooltip>
|
<Tooltip tip="Channel Members" placement="left">
|
||||||
</li>
|
<IconPeople />
|
||||||
</ul>
|
</Tooltip>
|
||||||
</>
|
</li>
|
||||||
}
|
</ul>
|
||||||
header={
|
<hr className="divider" />
|
||||||
<StyledHeader className="head">
|
<ul className="apps">
|
||||||
<div className="txt">
|
<li className="app">
|
||||||
<ChannelIcon personal={!is_public} />
|
<Tooltip tip="Webrowse" placement="left">
|
||||||
<span className="title">{name}</span>
|
<img src={webrowseIcon} alt="app icon" />
|
||||||
<span className="desc">{description}</span>
|
</Tooltip>
|
||||||
</div>
|
</li>
|
||||||
</StyledHeader>
|
<li className="app">
|
||||||
}
|
<Tooltip tip="BoardOS" placement="left">
|
||||||
contacts={
|
<img src={boardosIcon} alt="app icon" />
|
||||||
membersVisible ? (
|
</Tooltip>
|
||||||
<>
|
</li>
|
||||||
<StyledContacts>
|
</ul>
|
||||||
{addVisible && (
|
</>
|
||||||
<div className="add" onClick={toggleAddVisible}>
|
}
|
||||||
<img className="icon" src={addIcon} />
|
header={
|
||||||
<div className="txt">Add members</div>
|
<StyledHeader className="head">
|
||||||
</div>
|
<div className="txt">
|
||||||
)}
|
<ChannelIcon personal={!is_public} />
|
||||||
{memberIds.map((uid) => {
|
<span className="title">{name}</span>
|
||||||
return <Contact key={uid} uid={uid} dm popover />;
|
<span className="desc">{description}</span>
|
||||||
})}
|
</div>
|
||||||
</StyledContacts>
|
</StyledHeader>
|
||||||
</>
|
}
|
||||||
) : null
|
contacts={
|
||||||
}
|
membersVisible ? (
|
||||||
>
|
<>
|
||||||
<StyledChannelChat ref={ref}>
|
<StyledContacts>
|
||||||
<div className="info">
|
{addVisible && (
|
||||||
<h2 className="title">Welcome to #{name} !</h2>
|
<div className="add" onClick={toggleAddVisible}>
|
||||||
<p className="desc">This is the start of the #{name} channel. </p>
|
<img className="icon" src={addIcon} />
|
||||||
<NavLink to={`/setting/channel/${cid}?f=${pathname}`} className="edit">
|
<div className="txt">Add members</div>
|
||||||
<EditIcon className="icon" />
|
</div>
|
||||||
Edit Channel
|
)}
|
||||||
</NavLink>
|
{memberIds.map((uid) => {
|
||||||
</div>
|
return <Contact key={uid} uid={uid} dm popover />;
|
||||||
<div className="feed">
|
})}
|
||||||
{[...msgIds]
|
</StyledContacts>
|
||||||
.sort((a, b) => {
|
</>
|
||||||
return Number(a) - Number(b);
|
) : null
|
||||||
})
|
}
|
||||||
.map((mid, idx) => {
|
>
|
||||||
const curr = messageData[mid];
|
<StyledChannelChat ref={ref}>
|
||||||
if (!curr) return null;
|
<div className="info">
|
||||||
const isFirst = idx == 0;
|
<h2 className="title">Welcome to #{name} !</h2>
|
||||||
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
|
<p className="desc">This is the start of the #{name} channel. </p>
|
||||||
const read = curr?.from_uid == loginUid || mid <= readIndex;
|
<NavLink
|
||||||
return renderMessageFragment({
|
to={`/setting/channel/${cid}?f=${pathname}`}
|
||||||
selectMode: !!selects,
|
className="edit"
|
||||||
updateReadIndex: updateReadDebounced,
|
>
|
||||||
read,
|
<EditIcon className="icon" />
|
||||||
isFirst,
|
Edit Channel
|
||||||
prev,
|
</NavLink>
|
||||||
curr,
|
</div>
|
||||||
contextId: cid,
|
<div className="feed">
|
||||||
context: 'channel'
|
{[...msgIds]
|
||||||
});
|
.sort((a, b) => {
|
||||||
})}
|
return Number(a) - Number(b);
|
||||||
</div>
|
})
|
||||||
</StyledChannelChat>
|
.map((mid, idx) => {
|
||||||
{/* {unreads != 0 && (
|
const curr = messageData[mid];
|
||||||
|
if (!curr) return null;
|
||||||
|
const isFirst = idx == 0;
|
||||||
|
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
|
||||||
|
const read = curr?.from_uid == loginUid || mid <= readIndex;
|
||||||
|
return renderMessageFragment({
|
||||||
|
selectMode: !!selects,
|
||||||
|
updateReadIndex: updateReadDebounced,
|
||||||
|
read,
|
||||||
|
isFirst,
|
||||||
|
prev,
|
||||||
|
curr,
|
||||||
|
contextId: cid,
|
||||||
|
context: "channel",
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</StyledChannelChat>
|
||||||
|
{/* {unreads != 0 && (
|
||||||
<StyledNotification>
|
<StyledNotification>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{unreads} new messages
|
{unreads} new messages
|
||||||
@@ -238,7 +266,7 @@ export default function ChannelChat({ cid = '', dropFiles = [] }) {
|
|||||||
</button>
|
</button>
|
||||||
</StyledNotification>
|
</StyledNotification>
|
||||||
)} */}
|
)} */}
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
// import { useState, useEffect } from "react";
|
// import { useState, useEffect } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useDebounce } from "rooks";
|
import { useDebounce } from "rooks";
|
||||||
|
import Tippy from "@tippyjs/react";
|
||||||
|
import FavList from "../FavList";
|
||||||
|
|
||||||
import Tooltip from "../../../common/component/Tooltip";
|
import Tooltip from "../../../common/component/Tooltip";
|
||||||
import alertIcon from "../../../assets/icons/alert.svg?url";
|
import FavIcon from "../../../assets/icons/bookmark.svg";
|
||||||
import pinIcon from "../../../assets/icons/pin.svg?url";
|
|
||||||
// import searchIcon from "../../../assets/icons/search.svg?url";
|
// import searchIcon from "../../../assets/icons/search.svg?url";
|
||||||
|
import IconHeadphone from "../../../assets/icons/headphone.svg";
|
||||||
|
|
||||||
import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
|
import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
|
||||||
import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
|
import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
|
||||||
import useChatScroll from "../../../common/hook/useChatScroll";
|
import useChatScroll from "../../../common/hook/useChatScroll";
|
||||||
@@ -48,15 +52,37 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
|
|||||||
aside={
|
aside={
|
||||||
<>
|
<>
|
||||||
<ul className="tools">
|
<ul className="tools">
|
||||||
|
<li className="tool">
|
||||||
|
<IconHeadphone />
|
||||||
|
</li>
|
||||||
{/* <li className="tool">
|
{/* <li className="tool">
|
||||||
<img src={searchIcon} alt="opt icon" />
|
|
||||||
</li> */}
|
|
||||||
<li className="tool">
|
|
||||||
<img src={alertIcon} alt="opt icon" />
|
<img src={alertIcon} alt="opt icon" />
|
||||||
</li>
|
</li> */}
|
||||||
<li className="tool">
|
<Tooltip tip="Favorite" placement="left">
|
||||||
<img src={pinIcon} alt="opt icon" />
|
<Tippy
|
||||||
</li>
|
// onShow={() => {
|
||||||
|
// setToolVisible('favorite');
|
||||||
|
// }}
|
||||||
|
// onHide={() => {
|
||||||
|
// setToolVisible('');
|
||||||
|
// }}
|
||||||
|
delay={[0, 0]}
|
||||||
|
duration={0}
|
||||||
|
placement="left-start"
|
||||||
|
popperOptions={{ strategy: "fixed" }}
|
||||||
|
offset={[0, 180]}
|
||||||
|
interactive
|
||||||
|
trigger="click"
|
||||||
|
content={<FavList uid={uid} />}
|
||||||
|
>
|
||||||
|
<li className={`tool fav`}>
|
||||||
|
<FavIcon />
|
||||||
|
</li>
|
||||||
|
</Tippy>
|
||||||
|
</Tooltip>
|
||||||
|
{/* <li className="tool fav">
|
||||||
|
<FavIcon />
|
||||||
|
</li> */}
|
||||||
</ul>
|
</ul>
|
||||||
<hr className="divider" />
|
<hr className="divider" />
|
||||||
<ul className="apps">
|
<ul className="apps">
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// import React from "react";
|
// import React from "react";
|
||||||
// import { useSelector } from "react-redux";
|
// import { useSelector } from "react-redux";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import SavedMessage from "../../../common/component/Message/SavedMessage";
|
import SavedMessage from "../../common/component/Message/SavedMessage";
|
||||||
import IconSurprise from "../../../assets/icons/emoji.suprise.svg";
|
import IconSurprise from "../../assets/icons/emoji.suprise.svg";
|
||||||
// import IconForward from "../../../assets/icons/forward.svg";
|
// import IconForward from "../../../assets/icons/forward.svg";
|
||||||
import IconBookmark from "../../../assets/icons/bookmark.svg";
|
import IconBookmark from "../../assets/icons/bookmark.svg";
|
||||||
import useFavMessage from "../../../common/hook/useFavMessage";
|
import useFavMessage from "../../common/hook/useFavMessage";
|
||||||
const Styled = styled.div`
|
const Styled = styled.div`
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: #f9fafb;
|
background: #f9fafb;
|
||||||
@@ -82,8 +82,8 @@ const Styled = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export default function FavList({ cid = null }) {
|
export default function FavList({ cid = null, uid = null }) {
|
||||||
const { favorites, removeFavorite } = useFavMessage(cid);
|
const { favorites, removeFavorite } = useFavMessage({ cid, uid });
|
||||||
const handleRemove = (evt) => {
|
const handleRemove = (evt) => {
|
||||||
const { id } = evt.currentTarget.dataset;
|
const { id } = evt.currentTarget.dataset;
|
||||||
console.log("remove fav", id);
|
console.log("remove fav", id);
|
||||||
@@ -40,7 +40,7 @@ const Styled = styled.div`
|
|||||||
export default function Operations({ context, id }) {
|
export default function Operations({ context, id }) {
|
||||||
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
|
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
|
||||||
const { canDelete } = useDeleteMessage();
|
const { canDelete } = useDeleteMessage();
|
||||||
const { addFavorite } = useFavMessage(id);
|
const { addFavorite } = useFavMessage({});
|
||||||
const mids = useSelector(
|
const mids = useSelector(
|
||||||
(store) => store.ui.selectMessages[`${context}_${id}`]
|
(store) => store.ui.selectMessages[`${context}_${id}`]
|
||||||
);
|
);
|
||||||
@@ -50,9 +50,14 @@ export default function Operations({ context, id }) {
|
|||||||
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
|
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
|
||||||
};
|
};
|
||||||
const handleFav = async () => {
|
const handleFav = async () => {
|
||||||
await addFavorite(mids);
|
const added = await addFavorite(mids);
|
||||||
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
|
if (added) {
|
||||||
toast.success("Messages Saved!");
|
console.log("added", added);
|
||||||
|
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
|
||||||
|
toast.success("Messages Saved!");
|
||||||
|
} else {
|
||||||
|
toast.error("Operation Failed!");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const toggleDeleteModal = (isSuccess = false) => {
|
const toggleDeleteModal = (isSuccess = false) => {
|
||||||
setDeleteModalVisible((prev) => !prev);
|
setDeleteModalVisible((prev) => !prev);
|
||||||
|
|||||||
@@ -2,17 +2,12 @@
|
|||||||
import Styled from "./styled";
|
import Styled from "./styled";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import SavedMessage from "../../common/component/Message/SavedMessage";
|
import SavedMessage from "../../common/component/Message/SavedMessage";
|
||||||
// import Masonry from "masonry-layout";
|
import dayjs from "dayjs";
|
||||||
// import waterfall from "waterfall.js/src/waterfall";
|
|
||||||
// import { Views } from "../../app/config";
|
|
||||||
// import View from "./View";
|
|
||||||
// import Search from "./Search";
|
|
||||||
// import Filter from "./Filter";
|
|
||||||
// import FileBox from "../../common/component/FileBox";
|
|
||||||
function FavsPage() {
|
function FavsPage() {
|
||||||
// const listContainerRef = useRef(null);
|
// const listContainerRef = useRef(null);
|
||||||
// const [filter, setFilter] = useState({});
|
// const [filter, setFilter] = useState({});
|
||||||
const { favorites } = useSelector((store) => {
|
const { favorites } = useSelector((store) => {
|
||||||
|
console.log("favs", store.favorites);
|
||||||
return {
|
return {
|
||||||
favorites: store.favorites,
|
favorites: store.favorites,
|
||||||
// channelMessage: store.channelMessage,
|
// channelMessage: store.channelMessage,
|
||||||
@@ -21,8 +16,22 @@ function FavsPage() {
|
|||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<Styled>
|
<Styled>
|
||||||
{favorites.map(({ id, created_at }) => {
|
{favorites.map(({ id, created_at, messages }) => {
|
||||||
return <SavedMessage key={id} id={id} />;
|
const [
|
||||||
|
{
|
||||||
|
source: { gid, uid },
|
||||||
|
},
|
||||||
|
] = messages;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fav" key={id}>
|
||||||
|
<h4 className="tip">
|
||||||
|
{gid ? `gid:${gid}` : `uid:${uid}`}{" "}
|
||||||
|
{dayjs(created_at).format("YYYY-MM-DD")}
|
||||||
|
</h4>
|
||||||
|
<SavedMessage key={id} id={id} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</Styled>
|
</Styled>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,17 @@ const Styled = styled.div`
|
|||||||
margin: 8px 24px 10px 0;
|
margin: 8px 24px 10px 0;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
.fav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.tip {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default Styled;
|
export default Styled;
|
||||||
|
|||||||
Reference in New Issue
Block a user