diff --git a/src/common/component/Message/Commands.js b/src/common/component/Message/Commands.js index 4c089f2f..926166f8 100644 --- a/src/common/component/Message/Commands.js +++ b/src/common/component/Message/Commands.js @@ -69,9 +69,9 @@ export default function Commands({ from_uid = 0, toggleEditMessage, }) { - const { addFavorite, isFavorited } = useFavMessage( - context == "channel" ? contextId : null - ); + const { addFavorite, isFavorited } = useFavMessage({ + cid: context == "channel" ? contextId : null, + }); const [mids, setMids] = useState([]); const dispatch = useDispatch(); const [pinModalVisible, setPinModalVisible] = useState(false); @@ -122,8 +122,12 @@ export default function Commands({ toast.success("Favorited!"); return; } - await addFavorite(mid); - toast.success("Added Favorites!"); + const added = await addFavorite(mid); + if (added) { + toast.success("Added Favorites!"); + } else { + toast.error("Added Favorites Failed!"); + } }; useEffect(() => { if (isUnpinSuccess) { diff --git a/src/common/component/Message/SavedMessage.js b/src/common/component/Message/SavedMessage.js index 9b3b2a8b..245f868f 100644 --- a/src/common/component/Message/SavedMessage.js +++ b/src/common/component/Message/SavedMessage.js @@ -14,7 +14,7 @@ const StyledSaved = styled.div` padding: 8px; `; const SavedMessage = ({ cid, id }) => { - const { favorites } = useFavMessage(cid); + const { favorites } = useFavMessage({ cid }); const [fav, setFav] = useState(null); const [messages, setMessages] = useState(null); useEffect(() => { diff --git a/src/common/hook/useFavMessage.js b/src/common/hook/useFavMessage.js index 5d78e167..5290d24e 100644 --- a/src/common/hook/useFavMessage.js +++ b/src/common/hook/useFavMessage.js @@ -4,21 +4,20 @@ import { useLazyRemoveFavoriteQuery, useFavoriteMessageMutation, } from "../../app/services/message"; -export default function useFavMessage(cid = null) { +export default function useFavMessage({ cid = null, uid = null }) { const [removeFav] = useLazyRemoveFavoriteQuery(); const [addFav] = useFavoriteMessageMutation(); const [favorites, setFavorites] = useState([]); const { favs = [] } = useSelector((store) => { return { - // mids: store.channelMessage.byId[cid], favs: store.favorites, - // loginUser: store.contacts.byId[store.authData.uid], }; }); const addFavorite = async (mid = []) => { const mids = Array.isArray(mid) ? mid.map((i) => +i) : [+mid]; if (mids.length == 0) return; - await addFav(mids); + const { error = null } = await addFav(mids); + return !error; }; const removeFavorite = (id) => { if (!id) return; @@ -36,16 +35,23 @@ export default function useFavMessage(cid = null) { return mids.findIndex((i) => i == mid) > -1; }; useEffect(() => { - const filtereds = cid + let filtereds = []; + filtereds = cid ? favs.filter((f) => { if (!f.messages) return false; return f.messages.every((m) => m.source.gid == cid); }) : favs; - console.log("filtered", filtereds); - setFavorites(filtereds); - }, [cid, favs]); + filtereds = uid + ? filtereds.filter((f) => { + 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 { isFavorited, addFavorite, diff --git a/src/routes/chat/ChannelChat/index.js b/src/routes/chat/ChannelChat/index.js index eba27cee..ac9c78ba 100644 --- a/src/routes/chat/ChannelChat/index.js +++ b/src/routes/chat/ChannelChat/index.js @@ -1,231 +1,259 @@ -import { useState } from 'react'; -import { useDebounce } from 'rooks'; -import { useSelector } from 'react-redux'; -import PinList from './PinList'; -import FavList from './FavList'; -import { useReadMessageMutation } from '../../../app/services/message'; -import useChatScroll from '../../../common/hook/useChatScroll'; -import ChannelIcon from '../../../common/component/ChannelIcon'; -import Tooltip from '../../../common/component/Tooltip'; -import Contact from '../../../common/component/Contact'; -import Layout from '../Layout'; -import { renderMessageFragment } from '../utils'; -import EditIcon from '../../../assets/icons/edit.svg'; +import { useState } from "react"; +import { useDebounce } from "rooks"; +import { useSelector } from "react-redux"; +import PinList from "./PinList"; +import FavList from "../FavList"; +import { useReadMessageMutation } from "../../../app/services/message"; +import useChatScroll from "../../../common/hook/useChatScroll"; +import ChannelIcon from "../../../common/component/ChannelIcon"; +import Tooltip from "../../../common/component/Tooltip"; +import Contact from "../../../common/component/Contact"; +import Layout from "../Layout"; +import { renderMessageFragment } from "../utils"; +import EditIcon from "../../../assets/icons/edit.svg"; // import alertIcon from "../../../assets/icons/alert.svg?url"; -import IconFav from '../../../assets/icons/bookmark.svg'; -import IconPeople from '../../../assets/icons/people.svg'; -import IconPin from '../../../assets/icons/pin.svg'; +import IconFav from "../../../assets/icons/bookmark.svg"; +import IconPeople from "../../../assets/icons/people.svg"; +import IconPin from "../../../assets/icons/pin.svg"; // 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 webrowseIcon from '../../../assets/icons/app.webrowse.svg?url'; -import addIcon from '../../../assets/icons/add.svg?url'; +import IconHeadphone from "../../../assets/icons/headphone.svg"; +import boardosIcon from "../../../assets/icons/app.boardos.svg?url"; +import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url"; +import addIcon from "../../../assets/icons/add.svg?url"; import { - // StyledNotification, - StyledContacts, - StyledChannelChat, - StyledHeader -} from './styled'; -import ChannelInviteModal from '../../../common/component/ChannelInviteModal'; -import { NavLink, useLocation } from 'react-router-dom'; -import Tippy from '@tippyjs/react'; + // StyledNotification, + StyledContacts, + StyledChannelChat, + StyledHeader, +} from "./styled"; +import ChannelInviteModal from "../../../common/component/ChannelInviteModal"; +import { NavLink, useLocation } from "react-router-dom"; +import Tippy from "@tippyjs/react"; -export default function ChannelChat({ cid = '', dropFiles = [] }) { - const [toolVisible, setToolVisible] = useState(''); - const { pathname } = useLocation(); - const [updateReadIndex] = useReadMessageMutation(); - const updateReadDebounced = useDebounce(updateReadIndex, 300); - const [membersVisible, setMembersVisible] = useState(true); - const [addMemberModalVisible, setAddMemberModalVisible] = useState(false); - // const dispatch = useDispatch(); - const { selects, msgIds, userIds, data, messageData, loginUid, loginUser, footprint } = - useSelector((store) => { - 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 || {} - }; +export default function ChannelChat({ cid = "", dropFiles = [] }) { + const [toolVisible, setToolVisible] = useState(""); + const { pathname } = useLocation(); + const [updateReadIndex] = useReadMessageMutation(); + const updateReadDebounced = useDebounce(updateReadIndex, 300); + const [membersVisible, setMembersVisible] = useState(true); + const [addMemberModalVisible, setAddMemberModalVisible] = useState(false); + // const dispatch = useDispatch(); + const { + selects, + msgIds, + userIds, + data, + messageData, + loginUid, + loginUser, + footprint, + } = useSelector((store) => { + 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 handleClearUnreads = () => { - // dispatch(readMessage(msgIds)); - // }; - const toggleMembersVisible = () => { - setMembersVisible((prev) => !prev); - }; - const toggleAddVisible = () => { - setAddMemberModalVisible((prev) => !prev); - }; + const ref = useChatScroll(msgIds); + // const handleClearUnreads = () => { + // dispatch(readMessage(msgIds)); + // }; + const toggleMembersVisible = () => { + setMembersVisible((prev) => !prev); + }; + const toggleAddVisible = () => { + setAddMemberModalVisible((prev) => !prev); + }; - const { name, description, is_public, members = [], owner } = data; - const memberIds = is_public ? userIds : members; - const addVisible = loginUser?.is_admin || owner == loginUid; - console.log('channel message list', msgIds); - const readIndex = footprint.readChannels[cid]; - const pinCount = data?.pinned_messages?.length || 0; - return ( - <> - {addMemberModalVisible && } - - +
+ + + } + header={ + +
+ + {name} + {description} +
+
+ } + contacts={ + membersVisible ? ( + <> + + {addVisible && ( +
+ +
Add members
+
+ )} + {memberIds.map((uid) => { + return ; + })} +
+ + ) : null + } + > + +
+

Welcome to #{name} !

+

This is the start of the #{name} channel.

+ + + Edit Channel + +
+
+ {[...msgIds] + .sort((a, b) => { + return Number(a) - Number(b); + }) + .map((mid, idx) => { + 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", + }); + })} +
+
+ {/* {unreads != 0 && (
{unreads} new messages @@ -238,7 +266,7 @@ export default function ChannelChat({ cid = '', dropFiles = [] }) { )} */} - - - ); + + + ); } diff --git a/src/routes/chat/DMChat/index.js b/src/routes/chat/DMChat/index.js index 6009a093..9895ea82 100644 --- a/src/routes/chat/DMChat/index.js +++ b/src/routes/chat/DMChat/index.js @@ -1,10 +1,14 @@ // import { useState, useEffect } from "react"; import { useSelector } from "react-redux"; import { useDebounce } from "rooks"; +import Tippy from "@tippyjs/react"; +import FavList from "../FavList"; + import Tooltip from "../../../common/component/Tooltip"; -import alertIcon from "../../../assets/icons/alert.svg?url"; -import pinIcon from "../../../assets/icons/pin.svg?url"; +import FavIcon from "../../../assets/icons/bookmark.svg"; // 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 webrowseIcon from "../../../assets/icons/app.webrowse.svg?url"; import useChatScroll from "../../../common/hook/useChatScroll"; @@ -48,15 +52,37 @@ export default function DMChat({ uid = "", dropFiles = [] }) { aside={ <>
    +
  • + +
  • {/*
  • - opt icon -
  • */} -
  • opt icon -
  • -
  • - opt icon -
  • + */} + + { + // setToolVisible('favorite'); + // }} + // onHide={() => { + // setToolVisible(''); + // }} + delay={[0, 0]} + duration={0} + placement="left-start" + popperOptions={{ strategy: "fixed" }} + offset={[0, 180]} + interactive + trigger="click" + content={} + > +
  • + +
  • +
    +
    + {/*
  • + +
  • */}

    diff --git a/src/routes/chat/ChannelChat/FavList.js b/src/routes/chat/FavList.js similarity index 88% rename from src/routes/chat/ChannelChat/FavList.js rename to src/routes/chat/FavList.js index 44c36e76..43878564 100644 --- a/src/routes/chat/ChannelChat/FavList.js +++ b/src/routes/chat/FavList.js @@ -1,11 +1,11 @@ // import React from "react"; // import { useSelector } from "react-redux"; import styled from "styled-components"; -import SavedMessage from "../../../common/component/Message/SavedMessage"; -import IconSurprise from "../../../assets/icons/emoji.suprise.svg"; +import SavedMessage from "../../common/component/Message/SavedMessage"; +import IconSurprise from "../../assets/icons/emoji.suprise.svg"; // import IconForward from "../../../assets/icons/forward.svg"; -import IconBookmark from "../../../assets/icons/bookmark.svg"; -import useFavMessage from "../../../common/hook/useFavMessage"; +import IconBookmark from "../../assets/icons/bookmark.svg"; +import useFavMessage from "../../common/hook/useFavMessage"; const Styled = styled.div` padding: 16px; background: #f9fafb; @@ -82,8 +82,8 @@ const Styled = styled.div` } } `; -export default function FavList({ cid = null }) { - const { favorites, removeFavorite } = useFavMessage(cid); +export default function FavList({ cid = null, uid = null }) { + const { favorites, removeFavorite } = useFavMessage({ cid, uid }); const handleRemove = (evt) => { const { id } = evt.currentTarget.dataset; console.log("remove fav", id); diff --git a/src/routes/chat/Layout/Operations.js b/src/routes/chat/Layout/Operations.js index ef636135..b60ea790 100644 --- a/src/routes/chat/Layout/Operations.js +++ b/src/routes/chat/Layout/Operations.js @@ -40,7 +40,7 @@ const Styled = styled.div` export default function Operations({ context, id }) { const [deleteModalVisible, setDeleteModalVisible] = useState(false); const { canDelete } = useDeleteMessage(); - const { addFavorite } = useFavMessage(id); + const { addFavorite } = useFavMessage({}); const mids = useSelector( (store) => store.ui.selectMessages[`${context}_${id}`] ); @@ -50,9 +50,14 @@ export default function Operations({ context, id }) { dispatch(updateSelectMessages({ context, id, operation: "reset" })); }; const handleFav = async () => { - await addFavorite(mids); - dispatch(updateSelectMessages({ context, id, operation: "reset" })); - toast.success("Messages Saved!"); + const added = await addFavorite(mids); + if (added) { + console.log("added", added); + dispatch(updateSelectMessages({ context, id, operation: "reset" })); + toast.success("Messages Saved!"); + } else { + toast.error("Operation Failed!"); + } }; const toggleDeleteModal = (isSuccess = false) => { setDeleteModalVisible((prev) => !prev); diff --git a/src/routes/favs/index.js b/src/routes/favs/index.js index acc6e20d..834b2c9c 100644 --- a/src/routes/favs/index.js +++ b/src/routes/favs/index.js @@ -2,17 +2,12 @@ import Styled from "./styled"; import { useSelector } from "react-redux"; import SavedMessage from "../../common/component/Message/SavedMessage"; -// import Masonry from "masonry-layout"; -// 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"; +import dayjs from "dayjs"; function FavsPage() { // const listContainerRef = useRef(null); // const [filter, setFilter] = useState({}); const { favorites } = useSelector((store) => { + console.log("favs", store.favorites); return { favorites: store.favorites, // channelMessage: store.channelMessage, @@ -21,8 +16,22 @@ function FavsPage() { }); return ( - {favorites.map(({ id, created_at }) => { - return ; + {favorites.map(({ id, created_at, messages }) => { + const [ + { + source: { gid, uid }, + }, + ] = messages; + + return ( +
    +

    + {gid ? `gid:${gid}` : `uid:${uid}`}{" "} + {dayjs(created_at).format("YYYY-MM-DD")} +

    + +
    + ); })}
    ); diff --git a/src/routes/favs/styled.js b/src/routes/favs/styled.js index 19a1143b..94eada57 100644 --- a/src/routes/favs/styled.js +++ b/src/routes/favs/styled.js @@ -10,6 +10,17 @@ const Styled = styled.div` margin: 8px 24px 10px 0; border-radius: 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;