diff --git a/apps/builddao/widget/Bookmarks.jsx b/apps/builddao/widget/Bookmarks.jsx new file mode 100644 index 00000000..6c399cc8 --- /dev/null +++ b/apps/builddao/widget/Bookmarks.jsx @@ -0,0 +1,69 @@ +const { Post } = VM.require("buildhub.near/widget/components") || (() => <>); + +const accountId = props.accountId ?? context.accountId; + +const bookmarks = Social.getr(`${accountId}/graph/bookmark`, "final", { + withBlockHeight: true, +}); + +const StorageKey = "order"; +const order = Storage.privateGet(StorageKey); +const apps = useMemo(() => { + if (bookmarks === null || order === null) { + return []; + } + const starredApps = new Map(); + const path = []; + + const buildSrc = (node) => { + if (node.hasOwnProperty("")) { + starredApps.set(path.join("/"), node[":block"]); + } + Object.entries(node).forEach(([key, value]) => { + if (typeof value === "object") { + path.push(key); + buildSrc(value); + path.pop(); + } + }); + }; + + buildSrc(bookmarks ?? {}, [], starredApps); + let apps = [...starredApps.entries()]; + apps.sort((a, b) => b[1] - a[1]); + apps = apps.map((a) => a[0]); + apps.sort((a, b) => (order?.[a] || 0) - (order?.[b] || 0)); + Storage.privateSet( + StorageKey, + Object.fromEntries(apps.map((a, i) => [a, i + 1])) + ); + return apps; +}, [bookmarks, order]); + +let transformedArray = apps.map((item) => { + let splitParts = item.split("/"); + let accountId = splitParts[0]; + let lastPart = splitParts[splitParts.length - 1]; + let blockHeight = isNaN(lastPart) ? null : parseInt(lastPart); + + return { accountId, blockHeight }; +}); + +let filteredArray = transformedArray.filter( + (item) => item.blockHeight !== null +); + +return ( + <> + {(filteredArray ?? []).map((item) => ( + + ))} + {filteredArray.length === 0 && ( +

No Bookmarks Yet!

+ )} + +); diff --git a/apps/builddao/widget/Feed.jsx b/apps/builddao/widget/Feed.jsx index cb893808..b711cec5 100644 --- a/apps/builddao/widget/Feed.jsx +++ b/apps/builddao/widget/Feed.jsx @@ -139,6 +139,11 @@ const feeds = { - [Provide any context or details] `, }, + bookmarks: { + label: "Bookmarks", + icon: "bi-bookmark", + name: "bookmark", + }, }; const [activeFeed, setActiveFeed] = useState(type || "resolutions"); @@ -158,42 +163,48 @@ return ( {context.accountId ? ( - + activeFeed !== "bookmarks" ? ( + + ) : ( + + ) ) : ( )} - ( - - )} - /> + ]} + Item={(p) => ( + + )} + /> + )} ); diff --git a/apps/builddao/widget/components/post/BookmarkButton.jsx b/apps/builddao/widget/components/post/BookmarkButton.jsx index 693f3e3c..5ddf89d9 100644 --- a/apps/builddao/widget/components/post/BookmarkButton.jsx +++ b/apps/builddao/widget/components/post/BookmarkButton.jsx @@ -12,54 +12,51 @@ const bookmarks = Social.index("bookmark", item); const dataLoading = bookmarks === null; -const bookmarksByUsers = {}; +const bookmarksByUser = {}; (bookmarks || []).forEach((bookmark) => { if (bookmark.value.type === "bookmark") { - bookmarksByUsers[bookmark.accountId] = bookmark; + bookmarksByUser[bookmark.accountId] = bookmark; } else if (bookmark.value.type === "unbookmark") { - delete bookmarksByUsers[bookmark.accountId]; + delete bookmarksByUser[bookmark.accountId]; } }); + if (state.hasBookmark === true) { - bookmarksByUsers[context.accountId] = { + bookmarksByUser[context.accountId] = { accountId: context.accountId, }; } else if (state.hasBookmark === false) { - delete bookmarksByUsers[context.accountId]; + delete bookmarksByUser[context.accountId]; } -const accountsWithBookmarks = Object.keys(bookmarksByUsers); -const likeCount = accountsWithBookmarks.length; -const hasBookmark = context.accountId && !!bookmarksByUsers[context.accountId]; +const accountsWithBookmarks = Object.keys(bookmarksByUser); +const bookmarkCount = accountsWithBookmarks.length; +const hasBookmark = context.accountId && !!bookmarksByUser[context.accountId]; const bookmarkSvg = ( - + ); const bookmarkFillSvg = ( - + ); @@ -128,38 +125,66 @@ const BookmarkButton = styled.div` } `; -const likeClick = () => { +const bookmarkClick = () => { if (state.loading || dataLoading || !context.accountId) { return; } State.update({ loading: true, }); + const type = hasBookmark ? "unbookmark" : "bookmark"; const data = { index: { bookmark: JSON.stringify({ key: item, value: { - type: hasBookmark ? "unbookmark" : "bookmark", + type, }, }), }, }; + if (item.type === "social" && typeof item.path === "string") { + const keys = item.path.split("/"); + keys.push(item.blockHeight); + if (keys.length > 0) { + data.graph = { + bookmark: {}, + }; + let root = data.graph.bookmark; + keys.slice(0, -1).forEach((key) => { + root = root[key] = {}; + }); + root[keys[keys.length - 1]] = hasBookmark ? null : ""; + } + } + + if (!hasBookmark && props.notifyAccountId) { + data.index.notify = JSON.stringify({ + key: props.notifyAccountId, + value: { + type, + item, + }, + }); + } + Social.set(data, { onCommit: () => State.update({ loading: false, hasBookmark: !hasBookmark }), onCancel: () => State.update({ loading: false }), }); }; -const title = hasBookmark ? "Unbookmark" : "Bookmark"; +const title = hasBookmark + ? props.titleUnbookmark ?? "Unbookmark" + : props.titleBookmark ?? "Bookmark"; -return ( +const inner = (
{hasBookmark ? bookmarkFillSvg : bookmarkSvg} + {bookmarkCount > 0 && ( + + + + )}
); + +return props.tooltip ? ( + {title}} + > + {inner} + +) : ( + inner +);