From 6c5a0400e5977f22304b7b8c7bdbe36bca543ff7 Mon Sep 17 00:00:00 2001 From: Caleb Jacob Date: Mon, 11 Sep 2023 09:52:28 -0600 Subject: [PATCH 01/36] App library design changes --- src/AppLibrary/AppThumbnail.jsx | 1 + src/AppLibrary/IndexPage.jsx | 2 ++ src/AppLibrary/Search.jsx | 6 ++++-- src/ComponentCard.jsx | 18 ++++++++++-------- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/AppLibrary/AppThumbnail.jsx b/src/AppLibrary/AppThumbnail.jsx index 4717cc1a..5dfbd58b 100644 --- a/src/AppLibrary/AppThumbnail.jsx +++ b/src/AppLibrary/AppThumbnail.jsx @@ -6,6 +6,7 @@ const Thumbnail = styled.a` overflow: hidden; border-radius: 1.25rem; border: 1px solid var(--sand6); + background: #fff; position: relative; cursor: pointer; text-decoration: none !important; diff --git a/src/AppLibrary/IndexPage.jsx b/src/AppLibrary/IndexPage.jsx index 4a24a364..1b2e1dcf 100644 --- a/src/AppLibrary/IndexPage.jsx +++ b/src/AppLibrary/IndexPage.jsx @@ -256,6 +256,8 @@ return ( name: item.name, }, blockHeight: item.receipt_block_height, + hideBlockHeightTimestamp: true, + hideButtons: true, }} /> ); diff --git a/src/AppLibrary/Search.jsx b/src/AppLibrary/Search.jsx index a9b24847..99fd18d0 100644 --- a/src/AppLibrary/Search.jsx +++ b/src/AppLibrary/Search.jsx @@ -106,7 +106,7 @@ return ( props={{ onInput: handleOnInput, onQueryChange: handleOnQueryChange, - placeholder: "Search...", + placeholder: "Type keywords to search all apps...", }} /> @@ -116,7 +116,7 @@ return ( {state.results.length > 0 && ( <> -

All apps

+ Showing {state.results.length} results {state.results.map((result) => { @@ -132,6 +132,8 @@ return ( name: result.name, }, blockHeight: result.receipt_block_height, + hideBlockHeightTimestamp: true, + hideButtons: true, }} /> ); diff --git a/src/ComponentCard.jsx b/src/ComponentCard.jsx index b17d85c5..8fa3ad1c 100644 --- a/src/ComponentCard.jsx +++ b/src/ComponentCard.jsx @@ -150,7 +150,7 @@ const ButtonLink = styled.a` return ( - { + {!props.hideBlockHeightTimestamp && ( {" "} {" "} ago - } + )} @@ -200,11 +200,13 @@ return ( - - View Details - - Open - - + {!props.hideButtons && ( + + View Details + + Open + + + )} ); From a4e99223610f86bc40cb1243773e4d64e43b974a Mon Sep 17 00:00:00 2001 From: Caleb Jacob Date: Mon, 11 Sep 2023 11:36:13 -0600 Subject: [PATCH 02/36] Using new AppCard for AppLibrary --- src/AppLibrary/AppCard.jsx | 161 ++++++++++++++++++++++++++++++++ src/AppLibrary/AppThumbnail.jsx | 4 +- src/AppLibrary/IndexPage.jsx | 6 +- src/AppLibrary/Search.jsx | 6 +- 4 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 src/AppLibrary/AppCard.jsx diff --git a/src/AppLibrary/AppCard.jsx b/src/AppLibrary/AppCard.jsx new file mode 100644 index 00000000..cd54bcc8 --- /dev/null +++ b/src/AppLibrary/AppCard.jsx @@ -0,0 +1,161 @@ +const [accountId, unused, widgetName] = props.src.split("/"); +const appUrl = `#/${accountId}/widget/${widgetName}`; +const accountUrl = `#/${REPL_ACCOUNT}/widget/ProfilePage?accountId=${accountId}`; +const metadata = + props.metadata ?? + Social.get(`${accountId}/widget/${widgetName}/metadata/**`, "final") ?? + {}; +const tags = props.metadata + ? props.metadata.tags + : Object.keys(metadata.tags || {}); + +const Card = styled.div` + position: relative; + width: 100%; + border-radius: 12px; + background: #fff; + border: 1px solid #eceef0; + box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), + 0px 1px 2px rgba(16, 24, 40, 0.06); + overflow: hidden; +`; + +const CardBody = styled.div` + padding: 16px; + display: flex; + gap: 16px; + align-items: center; + + > * { + min-width: 0; + } +`; + +const CardContent = styled.div` + width: 100%; +`; + +const TextLink = styled.a` + display: block; + margin: 0; + font-size: 14px; + line-height: 18px; + color: ${(p) => (p.bold ? "#11181C !important" : "#687076 !important")}; + font-weight: ${(p) => (p.bold ? "600" : "400")}; + font-size: ${(p) => (p.small ? "12px" : "14px")}; + overflow: ${(p) => (p.ellipsis ? "hidden" : "visible")}; + text-overflow: ${(p) => (p.ellipsis ? "ellipsis" : "unset")}; + white-space: nowrap; + outline: none; + + &:focus, + &:hover { + text-decoration: underline; + } +`; + +const Text = styled.p` + margin: 0; + font-size: 14px; + line-height: 20px; + color: ${(p) => (p.bold ? "#11181C" : "#687076")}; + font-weight: ${(p) => (p.bold ? "600" : "400")}; + font-size: ${(p) => (p.small ? "12px" : "14px")}; + overflow: ${(p) => (p.ellipsis ? "hidden" : "")}; + text-overflow: ${(p) => (p.ellipsis ? "ellipsis" : "")}; + white-space: nowrap; + + i { + margin-right: 3px; + } +`; + +const Thumbnail = styled.a` + display: block; + width: 60px; + height: 60px; + flex-shrink: 0; + border: 1px solid #eceef0; + border-radius: 8px; + overflow: hidden; + outline: none; + transition: border-color 200ms; + + &:focus, + &:hover { + border-color: #d0d5dd; + } + + img { + object-fit: cover; + width: 100%; + height: 100%; + } +`; + +const TagsWrapper = styled.div` + position: relative; + margin-top: 4px; +`; + +const ButtonLink = styled.a` + padding: 8px; + height: 32px; + border: 1px solid #d7dbdf; + border-radius: 100px; + font-weight: 600; + font-size: 12px; + line-height: 15px; + text-align: center; + cursor: pointer; + color: ${(p) => (p.primary ? "#006ADC" : "#11181C")} !important; + background: #fbfcfd; + white-space: nowrap; + + &:hover, + &:focus { + background: #ecedee; + text-decoration: none; + outline: none; + } +`; + +return ( + + + + + + + + + {metadata.name || widgetName} + + + + @{accountId} + + + {tags.length > 0 && ( + + + + )} + + + +); diff --git a/src/AppLibrary/AppThumbnail.jsx b/src/AppLibrary/AppThumbnail.jsx index 5dfbd58b..7ff13c4f 100644 --- a/src/AppLibrary/AppThumbnail.jsx +++ b/src/AppLibrary/AppThumbnail.jsx @@ -1,4 +1,4 @@ -const appDetailsUrl = `#/${REPL_ACCOUNT}/widget/ComponentDetailsPage?src=${props.author}/widget/${props.widgetName}`; +const appUrl = `#/${props.author}/widget/${props.widgetName}`; const Thumbnail = styled.a` display: block; @@ -71,7 +71,7 @@ const ThumbnailTag = styled.span` `; return ( - + { return ( ); diff --git a/src/AppLibrary/Search.jsx b/src/AppLibrary/Search.jsx index 99fd18d0..9ad2faf5 100644 --- a/src/AppLibrary/Search.jsx +++ b/src/AppLibrary/Search.jsx @@ -123,17 +123,15 @@ return ( return ( ); From 0749d803f8f08c4a5d84ebf8ca14ee21bfe6ee13 Mon Sep 17 00:00:00 2001 From: Caleb Jacob Date: Mon, 11 Sep 2023 11:53:21 -0600 Subject: [PATCH 03/36] App card desgin changes --- src/AppLibrary/AppCard.jsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/AppLibrary/AppCard.jsx b/src/AppLibrary/AppCard.jsx index cd54bcc8..a56dc79c 100644 --- a/src/AppLibrary/AppCard.jsx +++ b/src/AppLibrary/AppCard.jsx @@ -12,16 +12,9 @@ const tags = props.metadata const Card = styled.div` position: relative; width: 100%; - border-radius: 12px; - background: #fff; - border: 1px solid #eceef0; - box-shadow: 0px 1px 3px rgba(16, 24, 40, 0.1), - 0px 1px 2px rgba(16, 24, 40, 0.06); - overflow: hidden; `; const CardBody = styled.div` - padding: 16px; display: flex; gap: 16px; align-items: center; From 6224f2304a5809f147a3b214c0f9b0584577744b Mon Sep 17 00:00:00 2001 From: Gabe Hamilton Date: Tue, 12 Sep 2023 11:28:42 -0600 Subject: [PATCH 04/36] Filter out accounts and posts that have been self moderated --- src/Posts.jsx | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Posts.jsx b/src/Posts.jsx index d8410919..406aa2bf 100644 --- a/src/Posts.jsx +++ b/src/Posts.jsx @@ -50,7 +50,7 @@ function selectTab(selectedTab) { loadMorePosts(); } -let filterUsersRaw = Social.get( +let gatewayModeratedUsersRaw = Social.get( `${moderatorAccount}/moderate/users`, "optimistic", { @@ -64,25 +64,52 @@ const selfFlaggedPosts = context.accountId }) : []; -if (filterUsersRaw === null) { +const selfModeration = context.accountId + ? Social.index("moderate", "main", { + accountId: context.accountId, + }) + : []; + +if (gatewayModeratedUsersRaw === null) { // haven't loaded filter list yet, return early return ""; } -const filterUsers = filterUsersRaw ? JSON.parse(filterUsersRaw) : []; +const gatewayModeratedUsers = gatewayModeratedUsersRaw ? JSON.parse(gatewayModeratedUsersRaw) : []; // get the full list of posts that the current user has flagged so // they can be hidden +// expecting moderation structure for accounts and posts like +// { moderate: { +// "account1.near": "block", +// "account2.near": { +// "100000123": "spam", +// }, +// } +// } +function matchesModeration(moderated, item) { + let accountFound = moderated[accountId]; + if (typeof accountFound === "undefined") { + return false; + } + if (typeof accountFound === "string") { + return true; + } + // match posts + return accountFound[item.block_height] !== "undefined"; +} + const shouldFilter = (item) => { return ( - filterUsers.includes(item.account_id) || + gatewayModeratedUsers.includes(item.account_id) || selfFlaggedPosts.find((flagged) => { return ( flagged?.value?.blockHeight === item.block_height && flagged?.value?.path.includes(item.account_id) ); - }) + }) || + matchesModeration(selfModeration, item) ); }; function fetchGraphQL(operationsDoc, operationName, variables) { @@ -222,7 +249,7 @@ const loadMorePosts = () => { const hasMore = state.postsCountLeft != state.posts.length; -if (!state.initLoadPostsAll && selfFlaggedPosts && filterUsers) { +if (!state.initLoadPostsAll && selfFlaggedPosts && selfModeration && gatewayModeratedUsers) { loadMorePosts(); State.update({ initLoadPostsAll: true }); } From e497ad1418a35878e86f611da8a3bb4c0663bc85 Mon Sep 17 00:00:00 2001 From: Caleb Jacob Date: Tue, 12 Sep 2023 13:26:51 -0600 Subject: [PATCH 05/36] Fixing grid overflow for app library --- src/AppLibrary/IndexPage.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AppLibrary/IndexPage.jsx b/src/AppLibrary/IndexPage.jsx index 0dc6fc1b..d0b6ea2c 100644 --- a/src/AppLibrary/IndexPage.jsx +++ b/src/AppLibrary/IndexPage.jsx @@ -168,11 +168,11 @@ const ThumbnailGrid = styled.div` const ContentGrid = styled.div` display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2rem; @media (max-width: 650px) { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); } `; From d17c1ac619e4f1bb867a4f24e37ce15a2ea3a39f Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Wed, 13 Sep 2023 17:52:41 +0300 Subject: [PATCH 06/36] Add notification preview --- .../Notifications/NotificationButton.jsx | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/NearOrg/Notifications/NotificationButton.jsx diff --git a/src/NearOrg/Notifications/NotificationButton.jsx b/src/NearOrg/Notifications/NotificationButton.jsx new file mode 100644 index 00000000..c78014a9 --- /dev/null +++ b/src/NearOrg/Notifications/NotificationButton.jsx @@ -0,0 +1,154 @@ +const accountId = context.accountId; +let { moderatorAccount, preview, href, previewItems, showMoreButton } = props; +moderatorAccount = moderatorAccount ?? "${REPL_MODERATOR}"; + +State.init({ + open: false, +}); + +if (context.loading || !accountId) return <>; + +const filterUsersRaw = Social.get( + `${moderatorAccount}/moderate/users`, //TODO + "optimistic", + { + subscribe: true, + } +); + +if (filterUsers === null) { + // haven't loaded filter list yet, return early + return <>; +} + +const filterUsers = filterUsersRaw ? JSON.parse(filterUsersRaw) : []; +const notificationFeedSrc = "${REPL_ACCOUNT}/widget/NotificationsPage"; +const lastBlockHeight = Storage.get("lastBlockHeight", notificationFeedSrc); +let notifications = + Social.index("notify", accountId, { + order: "asc", + from: (lastBlockHeight ?? 0) + 1, + subscribe: true, + }) || []; +notifications = notifications.filter((i) => !filterUsers.includes(i.accountId)); + +const notificationsCount = notifications.length || 0; + +const Wrapper = styled.div``; + +const ButtonWrapper = styled.div` + position: relative; + display: inline-flex; + margin: 1rem; +`; + +const Count = styled.span` + min-width: 13px; + height: 13px; + padding: 0 3px; + display: block; + color: var(--white); + background: var(--red8); + border-radius: 100px; + font-size: 10px; + line-height: 13px; + text-align: center; + font-weight: 600; + position: absolute; + top: -2px; + right: -1px; +`; + +const PreviewWrapper = styled.div` + position: absolute; + border-radius: 6px; + background: var(--white); + box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06), + 0px 0px 0px 1px rgba(0, 0, 0, 0.06); + top: 55px; + right: 75%; + max-width: 490px; + width: 100%; + visibility: hidden; + overflow: hidden; + transition: visibility 300ms ease; + transform-origin: right top; + + &[data-state="true"] { + visibility: visible; + animation: fadeIn 200ms ease; + } + [data-state='false'] { + animation: fadeOut 200ms ease; + } + + @keyframes fadeIn { + from { + visibility: hidden; + opacity: 0; + } + to { + visibility: visible; + opacity: 1; + } + } + + @keyframes fadeOut { + from { + visibility: visible; + opacity: 1; + } + to { + visibility: hidden; + opacity: 0; + } + } +`; + +const PreviewContent = styled.div` + display: flex; + flex-direction: column; +`; + +const Counter = ({ count }) => { + if (!count) return; + return {count}; +}; + +const Button = () => { + const icon = notificationsCount > 0 ? "ph ph-bell-ringing" : "ph ph-bell"; + return ( + + State.update({ open: !!state.open }), + }} + /> + + + ); +}; + +if (!preview) { + return