From fb7f6a4adbdcd1178a45da959188fca8b93b22bd Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:36:08 +0800 Subject: [PATCH 01/69] feat(copy): revsie "featured" copy --- lang/default.json | 4 ---- lang/en.json | 4 ---- lang/zh-Hans.json | 4 ---- lang/zh-Hant.json | 4 ---- src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx | 3 +-- src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx | 4 +--- 6 files changed, 2 insertions(+), 21 deletions(-) diff --git a/lang/default.json b/lang/default.json index d437cd2e28..5e67b3d6ea 100644 --- a/lang/default.json +++ b/lang/default.json @@ -1734,10 +1734,6 @@ "Rc4Oij": { "defaultMessage": "Firebolt" }, - "RkyEBL": { - "defaultMessage": "Featured", - "description": "src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx" - }, "RnKPVm": { "defaultMessage": "{articleCount} articles" }, diff --git a/lang/en.json b/lang/en.json index 6c61142f1f..42e5229aa7 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1734,10 +1734,6 @@ "Rc4Oij": { "defaultMessage": "Firebolt" }, - "RkyEBL": { - "defaultMessage": "Featured", - "description": "src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx" - }, "RnKPVm": { "defaultMessage": "{articleCount} articles" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index b85d698778..49213a590e 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -1734,10 +1734,6 @@ "Rc4Oij": { "defaultMessage": "火闪电" }, - "RkyEBL": { - "defaultMessage": "精华", - "description": "src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx" - }, "RnKPVm": { "defaultMessage": "{articleCount} 篇文章" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index def203a4de..fbbffb8901 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -1734,10 +1734,6 @@ "Rc4Oij": { "defaultMessage": "火閃電" }, - "RkyEBL": { - "defaultMessage": "精華", - "description": "src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx" - }, "RnKPVm": { "defaultMessage": "{articleCount} 篇文章" }, diff --git a/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx b/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx index d6f2b63293..14d1cb9802 100644 --- a/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx +++ b/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx @@ -238,8 +238,7 @@ const MainFeed = ({ feedType, camapign }: MainFeedProps) => { > )} diff --git a/src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx b/src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx index c7ee3db034..8d6cd48f20 100644 --- a/src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx +++ b/src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx @@ -74,9 +74,7 @@ const ArticleFeedsTabs = ({ }} title={intl.formatMessage({ defaultMessage: 'Featured', - id: 'RkyEBL', - description: - 'src/views/CampaignDetail/ArticleFeeds/Tabs/index.tsx', + id: 'CnPG8j', })} theme="green" /> From 0edf4ccd463f08ce8df6b045185b5b3d5168da4a Mon Sep 17 00:00:00 2001 From: Zeck Li <11781254+zeckli@users.noreply.github.com> Date: Tue, 5 Nov 2024 19:47:21 +0800 Subject: [PATCH 02/69] feat(tracker): add the event tracker for clicking collection tab in user profile page --- src/common/utils/analytics.ts | 1 + src/components/Tabs/index.tsx | 7 ++++++- src/views/User/UserTabs/index.tsx | 8 +++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/common/utils/analytics.ts b/src/common/utils/analytics.ts index 40fe0379ef..74c59c2a37 100644 --- a/src/common/utils/analytics.ts +++ b/src/common/utils/analytics.ts @@ -103,6 +103,7 @@ export interface ClickButtonProp { | 'newest' | 'campaign_detail_link' | `campaign_detail_tab_${string}` + | `user_profile_tab_${string}` pageType?: PageType pageComponent?: PageComponent } diff --git a/src/components/Tabs/index.tsx b/src/components/Tabs/index.tsx index c7889e523b..13fc088c21 100644 --- a/src/components/Tabs/index.tsx +++ b/src/components/Tabs/index.tsx @@ -36,7 +36,12 @@ const Tab: React.FC> = ({ if (href) { return ( -
  • +
  • {children} diff --git a/src/views/User/UserTabs/index.tsx b/src/views/User/UserTabs/index.tsx index ff27781ae0..df4bebdba9 100644 --- a/src/views/User/UserTabs/index.tsx +++ b/src/views/User/UserTabs/index.tsx @@ -1,7 +1,7 @@ import { useContext } from 'react' import { FormattedMessage } from 'react-intl' -import { toPath } from '~/common/utils' +import { analytics, toPath } from '~/common/utils' import { Tabs, useRoute, ViewerContext } from '~/components' import { TabsUserFragment } from '~/gql/graphql' @@ -53,6 +53,12 @@ const UserTabs = ({ {...userCollectionsPath} selected={isInPath('USER_COLLECTIONS')} count={collectionCount > 0 ? collectionCount : undefined} + onClick={() => { + analytics.trackEvent('click_button', { + type: `user_profile_tab_collection` as `user_profile_tab_${string}`, + pageType: 'user_profile', + }) + }} > From ce92c6d4dd8f516039fb92b79ff0a8f4c37b405b Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:54:29 +0800 Subject: [PATCH 03/69] feat(ipns): show IPNS (RSS) dialog only if user has ENS --- src/common/utils/wallet.ts | 6 +++--- src/views/User/UserProfile/DropdownActions/index.tsx | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/common/utils/wallet.ts b/src/common/utils/wallet.ts index 98aa371d45..b25eda65c6 100644 --- a/src/common/utils/wallet.ts +++ b/src/common/utils/wallet.ts @@ -1,11 +1,11 @@ import { Chain, configureChains, createConfig } from 'wagmi' import { - goerli, mainnet, optimism, optimismSepolia, polygon, polygonMumbai, + sepolia, } from 'wagmi/chains' import { InjectedConnector } from 'wagmi/connectors/injected' import { WalletConnectConnector } from 'wagmi/connectors/walletConnect' @@ -20,7 +20,7 @@ const alchemyId = process.env.NEXT_PUBLIC_ALCHEMY_KEY! export const featureSupportedChains = { billboard: isProd ? [optimism] : [optimismSepolia], curation: isProd ? [optimism] : [optimismSepolia], - ens: isProd ? [mainnet] : [goerli], + ens: isProd ? [mainnet] : [sepolia], } export const explorers = { @@ -34,7 +34,7 @@ export const explorers = { const defaultChains: Chain[] = isProd ? [mainnet, optimism] - : [goerli, optimismSepolia] + : [sepolia, optimismSepolia] export const { publicClient, chains } = configureChains(defaultChains, [ alchemyProvider({ apiKey: alchemyId }), diff --git a/src/views/User/UserProfile/DropdownActions/index.tsx b/src/views/User/UserProfile/DropdownActions/index.tsx index ac18a449af..edb2b6d9f2 100644 --- a/src/views/User/UserProfile/DropdownActions/index.tsx +++ b/src/views/User/UserProfile/DropdownActions/index.tsx @@ -4,10 +4,12 @@ import _pickBy from 'lodash/pickBy' import dynamic from 'next/dynamic' import { useContext } from 'react' import { FormattedMessage, useIntl } from 'react-intl' +import { useEnsName } from 'wagmi' import { ReactComponent as IconMore } from '@/public/static/icons/24px/more.svg' import { ReactComponent as IconRss } from '@/public/static/icons/24px/rss.svg' import { ReactComponent as IconShare } from '@/public/static/icons/24px/share.svg' +import { featureSupportedChains } from '~/common/utils' import { Button, Dropdown, @@ -230,11 +232,17 @@ const BaseDropdownActions = ({ const DropdownActions = ({ user, isMe, isInAside }: DropdownActionsProps) => { const viewer = useContext(ViewerContext) + const targetNetwork = featureSupportedChains.ens[0] + const { data: ensName } = useEnsName({ + address: user.info.ethAddress as `0x${string}`, + chainId: targetNetwork.id, + }) const controls = { hasEditProfile: isMe, hasBlockUser: !!viewer.id && !isMe, - hasRssFeed: user?.articles.totalCount > 0 && !!user?.info.ipnsKey, + hasRssFeed: + ensName && user?.articles.totalCount > 0 && !!user?.info.ipnsKey, } const WithShare = withDialog>( From ffff3490af4ff61784cfaf2f19d8fb218a515f94 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 8 Nov 2024 11:26:22 +0000 Subject: [PATCH 04/69] fix: add i18n command --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1efe6b2ba7..e3d7695d8f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - Install dependencies: `npm i` - Environment variables: `cp .env.local.example .env.local` - Run `npm run gen:type` +- Run `npm run i18n` - Run `npm run dev`, then go to `http://localhost:3000/` ### Build and run production server From c925f73cea82047ed1a79eaebe0b9dbbd287af66 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:26:09 +0800 Subject: [PATCH 05/69] feat(TagDigest): refactor TagDigest.Feed component --- src/common/enums/test.ts | 2 +- src/components/TagDigest/Feed/Feed.test.tsx | 25 +--- src/components/TagDigest/Feed/index.tsx | 114 +++--------------- .../TagDigest/Feed/styles.module.css | 56 ++------- 4 files changed, 32 insertions(+), 165 deletions(-) diff --git a/src/common/enums/test.ts b/src/common/enums/test.ts index 1dc25f7832..dde26d8eb6 100644 --- a/src/common/enums/test.ts +++ b/src/common/enums/test.ts @@ -32,7 +32,7 @@ export enum TEST_ID { DIGEST_USER_VERBOSE = 'digest/user/verbose', DIGEST_TAG_CONCISE = 'digest/tag/concise', DIGEST_TAG_FEED = 'digest/tag/feed', - DIGEST_TAG_FEED_COVER = 'digest/tag/feed/cover', + DIGEST_TAG_FEED_NUM_ARTICLES = 'digest/tag/feed/num-articles', DIGEST_TAG_RICH = 'digest/tag/rich', DIGEST_TAG_SIDEBAR = 'digest/tag/sidebar', DIGRET_CIRCLE_PLAIN = 'digest/circle/plain', diff --git a/src/components/TagDigest/Feed/Feed.test.tsx b/src/components/TagDigest/Feed/Feed.test.tsx index 764610a36e..8de9753b56 100644 --- a/src/components/TagDigest/Feed/Feed.test.tsx +++ b/src/components/TagDigest/Feed/Feed.test.tsx @@ -2,6 +2,7 @@ import mockRouter from 'next-router-mock' import { describe, expect, it } from 'vitest' import { TEST_ID } from '~/common/enums' +import { abbr } from '~/common/utils/number/abbr' import { render, screen } from '~/common/utils/test' import { TagDigest } from '~/components' import { MOCK_TAG } from '~/stories/mocks' @@ -18,24 +19,10 @@ describe('', () => { const $name = screen.getAllByText(MOCK_TAG.content)[0] // duplicated items in the mock expect($name).toBeInTheDocument() - const $articleCount = screen.getByText(MOCK_TAG.numArticles) - expect($articleCount).toBeInTheDocument() - - const $authorCount = screen.getByText(MOCK_TAG.numAuthors) - expect($authorCount).toBeInTheDocument() - - const $cover = screen.getByTestId(TEST_ID.DIGEST_TAG_FEED_COVER) - expect($cover).toBeInTheDocument() - mockRouter.push('/') - $cover.click() - expect(mockRouter.asPath).toContain(MOCK_TAG.slug) - - const $articleList = screen.getByRole('list') - expect($articleList).toBeInTheDocument() - const $articleListItems = screen.getAllByRole('listitem') - expect($articleListItems.length).toBe(4) - mockRouter.push('/') - $articleListItems[0].click() - expect(mockRouter.asPath).toContain(MOCK_TAG.articles.edges[0].node.slug) + const $numArticles = screen.getByTestId( + TEST_ID.DIGEST_TAG_FEED_NUM_ARTICLES + ) + expect($numArticles).toBeInTheDocument() + expect($numArticles).toHaveTextContent(`(${abbr(MOCK_TAG.numArticles, 2)})`) }) }) diff --git a/src/components/TagDigest/Feed/index.tsx b/src/components/TagDigest/Feed/index.tsx index cd7468068e..93c3a771a2 100644 --- a/src/components/TagDigest/Feed/index.tsx +++ b/src/components/TagDigest/Feed/index.tsx @@ -1,19 +1,10 @@ import gql from 'graphql-tag' import Link from 'next/link' -import { ReactComponent as IconDraft } from '@/public/static/icons/24px/draft.svg' -import { ReactComponent as IconUser } from '@/public/static/icons/24px/user.svg' -import IMAGE_TAG_COVER from '@/public/static/images/tag-cover.png' import { TEST_ID } from '~/common/enums' -import { captureClicks, numAbbr, toPath } from '~/common/utils' -import { - Card, - CardProps, - Icon, - PlainTag, - ResponsiveImage, - TextIcon, -} from '~/components' +import { toPath } from '~/common/utils' +import { abbr } from '~/common/utils/number/abbr' +import { CardProps } from '~/components' import { TagDigestFeedTagFragment } from '~/gql/graphql' import styles from './styles.module.css' @@ -27,24 +18,8 @@ const fragments = { fragment TagDigestFeedTag on Tag { id content - cover numArticles numAuthors - articles(input: { first: 3 }) { - edges { - cursor - node { - id - title - slug - shortHash - author { - id - userName - } - } - } - } } `, } @@ -55,79 +30,20 @@ const Feed = ({ tag, ...cardProps }: TagDigestFeedProps) => { tag, }) - const articles = tag.articles.edges + const numArticles = abbr(tag.numArticles, 2) return ( - -
    -
    - - -
    - } - size={12} - spacing={4} - color="greyDark" - > - {numAbbr(tag.numAuthors)} - - - } - size={12} - spacing={4} - color="greyDark" - > - {numAbbr(tag.numArticles)} - -
    -
    - -
    - - -
    - - - - - -
    -
    -
    - + + + {tag.content}  + + ({numArticles}) + + + ) } diff --git a/src/components/TagDigest/Feed/styles.module.css b/src/components/TagDigest/Feed/styles.module.css index cac15cbde4..7ba1341211 100644 --- a/src/components/TagDigest/Feed/styles.module.css +++ b/src/components/TagDigest/Feed/styles.module.css @@ -1,53 +1,17 @@ -.container { - position: relative; -} - -.header { - @mixin flex-center-space-between; -} - -.nums { - display: inline-flex; - flex-shrink: 0; +.tag { + @mixin transition; - & > * { - margin-left: var(--sp8); - } -} + display: flex; -.content { - @mixin flex-start-space-between; - - margin-top: var(--sp8); -} - -.cover { - position: relative; - display: inline-flex; - flex-shrink: 0; - width: 4.5rem; - height: 4.5rem; - margin-left: var(--sp8); - - & img { - @mixin object-fit-cover; - - background-color: var(--color-grey-lighter); - border-radius: 0.5rem; - } -} - -.articles { - & .title { + & .name { @mixin line-clamp; - font-size: var(--text13); - line-height: 1.5rem; - color: var(--color-grey-dark); + font-size: var(--text16); + line-height: 1.5rem; /* 24px */ + } - &:hover, - &:focus { - color: var(--color-black); - } + & .nums { + color: var(--color-grey); + word-break: keep-all; } } From 843247fdc6f4d0dc1eff68d161371495da795462 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:28:00 +0800 Subject: [PATCH 06/69] feat(TagDigest): update Feed stories --- src/stories/components/TagDigest/Feed.stories.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/stories/components/TagDigest/Feed.stories.tsx b/src/stories/components/TagDigest/Feed.stories.tsx index e18bc99a60..5596f784bc 100644 --- a/src/stories/components/TagDigest/Feed.stories.tsx +++ b/src/stories/components/TagDigest/Feed.stories.tsx @@ -21,3 +21,12 @@ export const Default = Template.bind({}) Default.args = { tag: MOCK_TAG as any, } + +export const LongName = Template.bind({}) +LongName.args = { + tag: { + ...MOCK_TAG, + content: + 'Matters.Town 是立足去中心化生態建立的,一個代碼開源、創作者自治的寫作社區。', + } as any, +} From 85008e18e67e7c9b22097c3121e9a34fe686e0b6 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:31:17 +0800 Subject: [PATCH 07/69] fix(TagDigest): remove unused props --- src/components/TagDigest/Feed/index.tsx | 8 ++++---- src/views/Tags/Feed.tsx | 9 +-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/components/TagDigest/Feed/index.tsx b/src/components/TagDigest/Feed/index.tsx index 93c3a771a2..ddfc6af9c3 100644 --- a/src/components/TagDigest/Feed/index.tsx +++ b/src/components/TagDigest/Feed/index.tsx @@ -4,14 +4,14 @@ import Link from 'next/link' import { TEST_ID } from '~/common/enums' import { toPath } from '~/common/utils' import { abbr } from '~/common/utils/number/abbr' -import { CardProps } from '~/components' import { TagDigestFeedTagFragment } from '~/gql/graphql' import styles from './styles.module.css' export type TagDigestFeedProps = { tag: TagDigestFeedTagFragment -} & CardProps + onClick?: () => void +} const fragments = { tag: gql` @@ -24,7 +24,7 @@ const fragments = { `, } -const Feed = ({ tag, ...cardProps }: TagDigestFeedProps) => { +const Feed = ({ tag, onClick }: TagDigestFeedProps) => { const path = toPath({ page: 'tagDetail', tag, @@ -33,7 +33,7 @@ const Feed = ({ tag, ...cardProps }: TagDigestFeedProps) => { const numArticles = abbr(tag.numArticles, 2) return ( - + {tag.content}  {
  • analytics.trackEvent('click_feed', { type: trackingType, From bf711a7677e2c1c623117edbb12c7545f22d44cb Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:28:41 +0800 Subject: [PATCH 08/69] feat(Tags): revise all tag pages --- src/views/Tags/gql.ts | 2 +- src/views/Tags/styles.module.css | 42 ++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/views/Tags/gql.ts b/src/views/Tags/gql.ts index ed4431ca8d..23261429a9 100644 --- a/src/views/Tags/gql.ts +++ b/src/views/Tags/gql.ts @@ -7,7 +7,7 @@ export const ALL_TAGS_HOTTEST = gql` viewer @connection(key: "viewerAllTagsHottest") { id recommendation { - tags(input: { first: 20, after: $after }) { + tags(input: { first: 30, after: $after }) { totalCount pageInfo { startCursor diff --git a/src/views/Tags/styles.module.css b/src/views/Tags/styles.module.css index 7cf203246b..5a3c1891e7 100644 --- a/src/views/Tags/styles.module.css +++ b/src/views/Tags/styles.module.css @@ -1,30 +1,40 @@ .tags { - /* FIXME: top header overlay by sticky tabs */ + margin-top: var(--sp24); - /* margin-top: 1px; */ + @media (--sm-up) { + margin-top: var(--sp32); + } } .list { - @media (--lg-up) { - display: grid; - grid-template-columns: repeat(2, 1fr); - - /* margin-top: calc(var(--sp16) * -1); */ - } + display: flex; + flex-wrap: wrap; & .listItem { - position: relative; - padding: var(--sp8) 0; + @mixin border-bottom-grey-light; - @media (--lg-up) { - padding: var(--sp16) 0; + position: relative; + flex: 0 0 50%; + padding-bottom: var(--sp20); + margin-bottom: var(--sp20); + border-style: dashed; + } - &:nth-child(2n) { - margin-left: var(--sp4); + @media (--sm-down) { + & .listItem { + &:nth-child(2n + 1) { + padding-right: var(--sp16); } + } + } - &:nth-child(2n + 1) { - margin-right: var(--sp24); + @media (--sm-up) { + & .listItem { + flex: 0 0 33.3333%; + + &:nth-child(3n + 1), + &:nth-child(3n + 2) { + padding-right: var(--sp16); } } } From 132b3f7926944082c8fb11588327b448142805a2 Mon Sep 17 00:00:00 2001 From: Woz <177856586+gitwoz@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:08:43 +0800 Subject: [PATCH 09/69] chore(release): v5.6.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 47f7c64427..242319ed45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matters-web", - "version": "5.6.5", + "version": "5.6.6", "description": "codebase of Matters' website", "author": "Matters ", "engines": { From 6b030dd58a0e2b4a5c703257ca230eddf6d8f704 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:50:56 +0800 Subject: [PATCH 10/69] fix(Tags): fix layout --- src/views/Tags/styles.module.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/views/Tags/styles.module.css b/src/views/Tags/styles.module.css index 5a3c1891e7..12bde92ba2 100644 --- a/src/views/Tags/styles.module.css +++ b/src/views/Tags/styles.module.css @@ -18,6 +18,10 @@ padding-bottom: var(--sp20); margin-bottom: var(--sp20); border-style: dashed; + + &:last-child { + flex-grow: 1; + } } @media (--sm-down) { From 2e8c164faddcbbc00c0e33f6e8e150e883220952 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:06:15 +0800 Subject: [PATCH 11/69] feat(AggregateResults): revise tag layout --- src/views/Search/AggregateResults/Tags.tsx | 26 +++++-------- src/views/Search/AggregateResults/gql.ts | 4 +- .../Search/AggregateResults/styles.module.css | 38 +++++++++++++++++++ 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/views/Search/AggregateResults/Tags.tsx b/src/views/Search/AggregateResults/Tags.tsx index e3952a98a0..07df228540 100644 --- a/src/views/Search/AggregateResults/Tags.tsx +++ b/src/views/Search/AggregateResults/Tags.tsx @@ -1,15 +1,14 @@ -import { Fragment, useEffect } from 'react' +import { useEffect } from 'react' import { FormattedMessage } from 'react-intl' import { LATER_SEARCH_RESULTS_LENGTH, MAX_SEARCH_RESULTS_LENGTH, } from '~/common/enums' -import { analytics, mergeConnections, toPath } from '~/common/utils' +import { analytics, mergeConnections } from '~/common/utils' import { EmptySearch, InfiniteScroll, - Menu, SpinnerBlock, TagDigest, Translate, @@ -104,18 +103,13 @@ const AggregateTagResults = () => { } > - +
      {edges.map( ({ node, cursor }, i) => node.__typename === 'Tag' && ( - - + analytics.trackEvent('click_feed', { type: 'search_tag', @@ -125,13 +119,11 @@ const AggregateTagResults = () => { searchKey: q, }) } - > - - - + /> + ) )} -
    + ) diff --git a/src/views/Search/AggregateResults/gql.ts b/src/views/Search/AggregateResults/gql.ts index dcb6469a87..964622c592 100644 --- a/src/views/Search/AggregateResults/gql.ts +++ b/src/views/Search/AggregateResults/gql.ts @@ -60,13 +60,13 @@ export const SEARCH_AGGREGATE_TAGS_PUBLIC = gql` cursor node { ... on Tag { - ...TagDigestConciseTag + ...TagDigestFeedTag } } } } } - ${TagDigest.Concise.fragments.tag} + ${TagDigest.Feed.fragments.tag} ` export const SEARCH_AGGREGATE_USERS_PUBLIC = gql` diff --git a/src/views/Search/AggregateResults/styles.module.css b/src/views/Search/AggregateResults/styles.module.css index f5cdeb0749..8da5cdd4de 100644 --- a/src/views/Search/AggregateResults/styles.module.css +++ b/src/views/Search/AggregateResults/styles.module.css @@ -45,3 +45,41 @@ .result-item { padding: var(--sp16); } + +.tagList { + display: flex; + flex-wrap: wrap; + + & .tagListItem { + @mixin border-bottom-grey-light; + + position: relative; + flex: 0 0 50%; + padding-bottom: var(--sp20); + margin-bottom: var(--sp20); + border-style: dashed; + + &:last-child { + flex-grow: 1; + } + } + + @media (--sm-down) { + & .tagListItem { + &:nth-child(2n + 1) { + padding-right: var(--sp16); + } + } + } + + @media (--sm-up) { + & .tagListItem { + flex: 0 0 33.3333%; + + &:nth-child(3n + 1), + &:nth-child(3n + 2) { + padding-right: var(--sp16); + } + } + } +} From 8d4bbe3c32471f6bc6d50dfe88a2f84463987b75 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:48:46 +0800 Subject: [PATCH 12/69] feat(AggregateResult): Revise title and tabs --- lang/default.json | 11 +++++ lang/en.json | 11 +++++ lang/zh-Hans.json | 11 +++++ lang/zh-Hant.json | 11 +++++ src/views/Search/AggregateResults/Tabs.tsx | 47 +++++++++++++++++++ src/views/Search/AggregateResults/index.tsx | 37 ++++++--------- .../Search/AggregateResults/styles.module.css | 28 +++++------ 7 files changed, 117 insertions(+), 39 deletions(-) create mode 100644 src/views/Search/AggregateResults/Tabs.tsx diff --git a/lang/default.json b/lang/default.json index 5e67b3d6ea..c133d95dbe 100644 --- a/lang/default.json +++ b/lang/default.json @@ -632,6 +632,10 @@ "defaultMessage": "Unpin from profile", "description": "src/views/User/Articles/PinBoard/UnPinButton/index.tsx" }, + "8GXAUX": { + "defaultMessage": "All results for", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "8KFsZN": { "defaultMessage": "Read Counts" }, @@ -2121,6 +2125,9 @@ "Y8zV4A": { "defaultMessage": "Write a comment" }, + "YDMrKK": { + "defaultMessage": "Users" + }, "YPMn9n": { "defaultMessage": "Please log in.", "description": "UNAUTHENTICATED" @@ -2347,6 +2354,10 @@ "cd/II9": { "defaultMessage": "{totalCount, plural, =1 {article} other {articles}}" }, + "cd8EmU": { + "defaultMessage": "of search results", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "cg1VJ2": { "defaultMessage": "Connect Wallet" }, diff --git a/lang/en.json b/lang/en.json index 42e5229aa7..e3544b6527 100644 --- a/lang/en.json +++ b/lang/en.json @@ -632,6 +632,10 @@ "defaultMessage": "Unpin from profile", "description": "src/views/User/Articles/PinBoard/UnPinButton/index.tsx" }, + "8GXAUX": { + "defaultMessage": "All results for", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "8KFsZN": { "defaultMessage": "Read Counts" }, @@ -2121,6 +2125,9 @@ "Y8zV4A": { "defaultMessage": "Write a comment" }, + "YDMrKK": { + "defaultMessage": "Users" + }, "YPMn9n": { "defaultMessage": "Please log in.", "description": "UNAUTHENTICATED" @@ -2347,6 +2354,10 @@ "cd/II9": { "defaultMessage": "{totalCount, plural, =1 {article} other {articles}}" }, + "cd8EmU": { + "defaultMessage": "", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "cg1VJ2": { "defaultMessage": "Connect Wallet" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 49213a590e..d3fd7fd9f6 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -632,6 +632,10 @@ "defaultMessage": "取消代表作", "description": "src/views/User/Articles/PinBoard/UnPinButton/index.tsx" }, + "8GXAUX": { + "defaultMessage": "有关", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "8KFsZN": { "defaultMessage": "阅读次数" }, @@ -2121,6 +2125,9 @@ "Y8zV4A": { "defaultMessage": "回复评论" }, + "YDMrKK": { + "defaultMessage": "用户" + }, "YPMn9n": { "defaultMessage": "请先登入再进行操作", "description": "UNAUTHENTICATED" @@ -2347,6 +2354,10 @@ "cd/II9": { "defaultMessage": "{totalCount, plural, =1 {篇文章} other {篇文章}}" }, + "cd8EmU": { + "defaultMessage": "的搜索结果", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "cg1VJ2": { "defaultMessage": "连接加密钱包" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index fbbffb8901..e0bb561f8e 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -632,6 +632,10 @@ "defaultMessage": "取消代表作", "description": "src/views/User/Articles/PinBoard/UnPinButton/index.tsx" }, + "8GXAUX": { + "defaultMessage": "有關", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "8KFsZN": { "defaultMessage": "閱讀次數" }, @@ -2121,6 +2125,9 @@ "Y8zV4A": { "defaultMessage": "回覆評論" }, + "YDMrKK": { + "defaultMessage": "用戶" + }, "YPMn9n": { "defaultMessage": "請先登入再進行操作", "description": "UNAUTHENTICATED" @@ -2347,6 +2354,10 @@ "cd/II9": { "defaultMessage": "{totalCount, plural, =1 {篇文章} other {篇文章}}" }, + "cd8EmU": { + "defaultMessage": "的檢索結果", + "description": "src/views/Search/AggregateResults/index.tsx" + }, "cg1VJ2": { "defaultMessage": "連接加密錢包" }, diff --git a/src/views/Search/AggregateResults/Tabs.tsx b/src/views/Search/AggregateResults/Tabs.tsx new file mode 100644 index 0000000000..8fdd8a44f8 --- /dev/null +++ b/src/views/Search/AggregateResults/Tabs.tsx @@ -0,0 +1,47 @@ +import { useIntl } from 'react-intl' + +import { SquareTabs } from '~/components' + +import styles from './styles.module.css' + +export type TABS = 'article' | 'user' | 'tag' + +type TabsProps = { + tab: TABS + setTab: (tab: TABS) => void +} + +export const Tabs = ({ tab, setTab }: TabsProps) => { + const intl = useIntl() + + return ( +
    + + setTab('article')} + title={intl.formatMessage({ + defaultMessage: 'Articles', + id: '3KNMbJ', + })} + /> + setTab('user')} + title={intl.formatMessage({ + defaultMessage: 'Users', + id: 'YDMrKK', + })} + /> + setTab('tag')} + title={intl.formatMessage({ + defaultMessage: 'Tags', + id: '1EYCdR', + })} + /> + +
    + ) +} diff --git a/src/views/Search/AggregateResults/index.tsx b/src/views/Search/AggregateResults/index.tsx index 883f231b30..17515ced70 100644 --- a/src/views/Search/AggregateResults/index.tsx +++ b/src/views/Search/AggregateResults/index.tsx @@ -1,8 +1,9 @@ import { useApolloClient } from '@apollo/react-hooks' import { useEffect, useState } from 'react' +import { FormattedMessage } from 'react-intl' import { getSearchType } from '~/common/utils' -import { Layout, SegmentedTabs, Translate, useRoute } from '~/components' +import { Layout, useRoute } from '~/components' import Articles from './Articles' import { @@ -11,6 +12,7 @@ import { SEARCH_AGGREGATE_USERS_PUBLIC, } from './gql' import styles from './styles.module.css' +import { TABS, Tabs } from './Tabs' import Tags from './Tags' import Users from './Users' @@ -60,37 +62,26 @@ const AggregateResults = () => { <>
    - +  {q}   - +
    - - updateType(Type.ARTICLE)} - > - - - updateType(Type.USER)} - > - - - updateType(Type.TAG)} - > - - - + void} /> {isArticle && } diff --git a/src/views/Search/AggregateResults/styles.module.css b/src/views/Search/AggregateResults/styles.module.css index 8da5cdd4de..496aa57c27 100644 --- a/src/views/Search/AggregateResults/styles.module.css +++ b/src/views/Search/AggregateResults/styles.module.css @@ -1,14 +1,12 @@ .title { @mixin flex-center-start; - padding: var(--sp24) var(--sp16) var(--sp16); + padding: var(--sp24) var(--sp16) 0; font-size: var(--text14); font-weight: var(--font-medium); color: var(--color-grey); - @media (--lg-up) { - @mixin border-bottom-grey; - + @media (--sm-up) { padding-right: 0; padding-left: 0; font-size: var(--text18); @@ -28,18 +26,6 @@ & .titleRight { white-space: nowrap; } - - @media (--sm-up) { - padding-bottom: var(--sp8); - } -} - -.aggregateSection { - padding: 0 var(--sp16); - - @media (--lg-up) { - padding: 0; - } } .result-item { @@ -49,6 +35,7 @@ .tagList { display: flex; flex-wrap: wrap; + margin-top: var(--sp32); & .tagListItem { @mixin border-bottom-grey-light; @@ -83,3 +70,12 @@ } } } + +.tabs { + padding: 0 var(--sp16); + margin: var(--sp32) 0 var(--sp16); + + @media (--sm-up) { + padding: 0; + } +} From 2bc924d383e7cc2a09e0d75c345db343933806da Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:45:33 +0800 Subject: [PATCH 13/69] feat(TagDetail): remove cover and revise header --- src/components/Icon/styles.module.css | 5 ++ src/components/Icon/withIcon.tsx | 1 + src/views/TagDetail/ArticlesCount/index.tsx | 2 +- .../TagDetail/ArticlesCount/styles.module.css | 6 +- src/views/TagDetail/index.tsx | 73 +++++-------------- src/views/TagDetail/styles.module.css | 20 ++--- 6 files changed, 37 insertions(+), 70 deletions(-) diff --git a/src/components/Icon/styles.module.css b/src/components/Icon/styles.module.css index 062f930480..6d6be1101f 100644 --- a/src/components/Icon/styles.module.css +++ b/src/components/Icon/styles.module.css @@ -42,6 +42,11 @@ height: 1.5rem; } + &.size28 { + width: 1.75rem; + height: 1.75rem; + } + &.size32 { width: 2rem; height: 2rem; diff --git a/src/components/Icon/withIcon.tsx b/src/components/Icon/withIcon.tsx index 03b8c68214..162fe85212 100644 --- a/src/components/Icon/withIcon.tsx +++ b/src/components/Icon/withIcon.tsx @@ -11,6 +11,7 @@ export type IconSize = | 20 | 22 | 24 + | 28 | 32 | 40 | 48 diff --git a/src/views/TagDetail/ArticlesCount/index.tsx b/src/views/TagDetail/ArticlesCount/index.tsx index 797f809690..1f5f45a83e 100644 --- a/src/views/TagDetail/ArticlesCount/index.tsx +++ b/src/views/TagDetail/ArticlesCount/index.tsx @@ -15,7 +15,7 @@ const ArticlesCount = ({ tag }: ArticlesCountProps) => { return (
    - {numAbbr(totalCount)} + {numAbbr(totalCount)}   { const { router } = useRoute() const viewer = useContext(ViewerContext) - const features = useFeatures() // feed type const { getQuery, setQuery } = useRoute() @@ -106,8 +102,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { // define permission const isOwner = tag?.owner?.id === viewer.id - const isEditor = (tag?.editors || []).some((t) => t.id === viewer.id) - const isMaintainer = isOwner || isEditor || viewer.isAdmin // Matty const title = '#' + normalizeTag(tag.content) const keywords = tag.content.split(/\s+/).filter(Boolean).map(normalizeTag) @@ -119,30 +113,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { */ return ( }> - - -
    - - -
    - - } - mode="transparent" - /> - { }} /> - +
    + } + color="black" + size={24} + spacing={4} + weight="medium" + > + {tag.content} + +
    - {features.tag_adoption && } - -
    -
    - - -
    - -
    - -
    +
    +
    - {tag.description && ( - -

    {tag.description}

    -
    - )} +
    + +
    diff --git a/src/views/TagDetail/styles.module.css b/src/views/TagDetail/styles.module.css index ae618b47fc..a4b546577c 100644 --- a/src/views/TagDetail/styles.module.css +++ b/src/views/TagDetail/styles.module.css @@ -1,16 +1,16 @@ -.info { - padding: 0 var(--sp16); - margin-bottom: var(--sp8); +.title { + @mixin flex-center-start; - @media (--sm-up) { - padding: 0; - } + height: 2.25rem; /* 36px; */ + margin: var(--sp32) 0; +} - & .top { - @mixin flex-center-space-between; +.info { + @mixin border-top-grey-light; + @mixin border-bottom-grey-light; + @mixin flex-center-space-between; - margin-top: var(--sp16); - } + padding: var(--sp16) 0; } .buttons { From becd38c488615f4ffb33ef61d5de0c2beff60459 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:15:11 +0800 Subject: [PATCH 14/69] feat(TagDetail): revise tabs --- src/views/TagDetail/index.tsx | 74 +++++++++------------------ src/views/TagDetail/styles.module.css | 5 ++ 2 files changed, 30 insertions(+), 49 deletions(-) diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index 18aadbb0ec..81a619ada9 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -1,6 +1,5 @@ -import dynamic from 'next/dynamic' import { useContext, useEffect, useState } from 'react' -import { FormattedMessage } from 'react-intl' +import { useIntl } from 'react-intl' import { ReactComponent as IconHashTag } from '@/public/static/icons/24px/hashtag.svg' import IMAGE_TAG_COVER from '@/public/static/images/tag-cover.png' @@ -18,8 +17,8 @@ import { Head, Icon, Layout, - SegmentedTabs, SpinnerBlock, + SquareTabs, TextIcon, Throw404, usePublicQuery, @@ -44,17 +43,12 @@ import { import RelatedTags from './RelatedTags' import styles from './styles.module.css' -const DynamicCommunity = dynamic(() => import('./Community'), { - ssr: false, - loading: () => , -}) - const validTagFeedTypes = ['hottest', 'latest', 'selected', 'creators'] as const type TagFeedType = (typeof validTagFeedTypes)[number] const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const { router } = useRoute() - const viewer = useContext(ViewerContext) + const intl = useIntl() // feed type const { getQuery, setQuery } = useRoute() @@ -81,7 +75,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const isSelected = feedType === 'selected' const isHottest = feedType === 'hottest' const isLatest = feedType === 'latest' - const isCreators = feedType === 'creators' useEffect(() => { // if selected feed is empty, switch to hottest feed @@ -100,9 +93,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { } }, []) - // define permission - const isOwner = tag?.owner?.id === viewer.id - const title = '#' + normalizeTag(tag.content) const keywords = tag.content.split(/\s+/).filter(Boolean).map(normalizeTag) const description = stripSpaces(tag.description) @@ -158,43 +148,29 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => {
    - - changeFeed('hottest')} - > - - - - changeFeed('latest')} - > - - - - {hasSelectedFeed && ( - changeFeed('selected')} - > - - - )} - - changeFeed('creators')} - > - - - - - {(isHottest || isLatest || isSelected) && ( - - )} +
    + + changeFeed('latest')} + title={intl.formatMessage({ + defaultMessage: 'Latest', + id: 'adThp5', + })} + /> + + changeFeed('hottest')} + title={intl.formatMessage({ + defaultMessage: 'Trending', + id: 'll/ufR', + })} + /> + +
    - {isCreators && } + ) } diff --git a/src/views/TagDetail/styles.module.css b/src/views/TagDetail/styles.module.css index a4b546577c..e4aa04cc18 100644 --- a/src/views/TagDetail/styles.module.css +++ b/src/views/TagDetail/styles.module.css @@ -13,6 +13,11 @@ padding: var(--sp16) 0; } +.tabs { + margin-top: var(--sp32); + margin-bottom: var(--sp12); +} + .buttons { display: inline-flex; gap: var(--sp16); From 4c53463f839603278eae155ab7a8140de91c3751 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:56:45 +0800 Subject: [PATCH 15/69] feat(TagDetail): remove unused control actions --- .../DropdownActions/DropdownActions.test.tsx | 31 +------------------ .../ArticleDigest/DropdownActions/index.tsx | 29 ----------------- src/components/ArticleDigest/Feed/index.tsx | 5 +-- src/views/TagDetail/Articles/index.tsx | 10 ------ 4 files changed, 2 insertions(+), 73 deletions(-) diff --git a/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx b/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx index 5ec21d4495..7d686fd2b6 100644 --- a/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx +++ b/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx @@ -190,19 +190,8 @@ describe('', () => { expect($archiveButton).toBeInTheDocument() }) - // hasSetTagSelected - // hasSetTagUnselected - // hasRemoveTag it('should render tag buttons', async () => { - render( - - ) + render() const $button = screen.getByLabelText('More Actions') expect($button).toBeInTheDocument() @@ -211,24 +200,6 @@ describe('', () => { $button.click() const $menu = screen.getByRole('menu') expect($menu).toBeInTheDocument() - - // hasSetTagSelected - const $setTagSelectedBtn = screen.getByRole('menuitem', { - name: 'Add to Featured', - }) - expect($setTagSelectedBtn).toBeInTheDocument() - - // hasUnsetTagSelected - const $setTagUnselectedBtn = screen.getByRole('menuitem', { - name: 'Unpin from Trending', - }) - expect($setTagUnselectedBtn).toBeInTheDocument() - - // hasRemoveTag - const $removeTagBtn = screen.getByRole('menuitem', { - name: 'Remove Article', - }) - expect($removeTagBtn).toBeInTheDocument() }) // hasSetTopCollection diff --git a/src/components/ArticleDigest/DropdownActions/index.tsx b/src/components/ArticleDigest/DropdownActions/index.tsx index 2e086e3ca6..ce0cac35c5 100644 --- a/src/components/ArticleDigest/DropdownActions/index.tsx +++ b/src/components/ArticleDigest/DropdownActions/index.tsx @@ -49,10 +49,7 @@ import { fragments } from './gql' import IPFSButton from './IPFSButton' import PinButton from './PinButton' import RemoveArticleCollectionButton from './RemoveArticleCollectionButton' -import RemoveTagButton from './RemoveTagButton' import SetBottomCollectionButton from './SetBottomCollectionButton' -import SetTagSelectedButton from './SetTagSelectedButton' -import SetTagUnselectedButton from './SetTagUnselectedButton' import SetTopCollectionButton from './SetTopCollectionButton' import ShareButton from './ShareButton' import styles from './styles.module.css' @@ -126,9 +123,6 @@ export interface DropdownActionsControls { // tag tagDetailId?: string - hasSetTagSelected?: boolean - hasSetTagUnselected?: boolean - hasRemoveTag?: boolean // campaign campaignId?: string @@ -163,9 +157,6 @@ interface Controls { hasExtend: boolean hasReport: boolean hasSticky: boolean - hasSetTagSelected: boolean - hasSetTagUnselected: boolean - hasRemoveTag: boolean } interface DialogProps { @@ -215,9 +206,6 @@ const BaseDropdownActions = ({ hasReport, hasSticky, hasArchive, - hasSetTagSelected, - hasSetTagUnselected, - hasRemoveTag, hasToggleCampaignFeatured, hasEdit, hasBookmark, @@ -278,16 +266,6 @@ const BaseDropdownActions = ({ )} - {hasSetTagSelected && tagDetailId && ( - - )} - {hasSetTagUnselected && tagDetailId && ( - - )} - {hasRemoveTag && tagDetailId && ( - - )} - {hasArchive && } {hasArchive && } @@ -412,10 +390,6 @@ const DropdownActions = (props: DropdownActionsProps) => { inCard, inUserArticles, - hasSetTagSelected, - hasSetTagUnselected, - hasRemoveTag, - hasEdit, hasArchive, hasBookmark = true, @@ -452,9 +426,6 @@ const DropdownActions = (props: DropdownActionsProps) => { ), hasArchive: !!hasArchive && isArticleAuthor && isActive && !viewer.isArchived, - hasSetTagSelected: !!hasSetTagSelected, - hasSetTagUnselected: !!hasSetTagUnselected, - hasRemoveTag: !!hasRemoveTag, hasEdit: !!hasEdit && isActive && isArticleAuthor, hasBookmark: !!hasBookmark, hasAddCollection: hasAddCollection && isActive && isArticleAuthor, diff --git a/src/components/ArticleDigest/Feed/index.tsx b/src/components/ArticleDigest/Feed/index.tsx index c0e8eec4d0..48c5ead69a 100644 --- a/src/components/ArticleDigest/Feed/index.tsx +++ b/src/components/ArticleDigest/Feed/index.tsx @@ -181,10 +181,7 @@ export const ArticleDigestFeed = React.memo( return ( prevArticle.subscribed === article.subscribed && prevArticle.articleState === article.articleState && - prevArticle.pinned === article.pinned && - prevProps.hasSetTagSelected === props.hasSetTagSelected && - prevProps.hasSetTagUnselected === props.hasSetTagUnselected && - prevProps.hasRemoveTag === props.hasRemoveTag + prevArticle.pinned === article.pinned ) } ) as MemoizedArticleDigestFeed diff --git a/src/views/TagDetail/Articles/index.tsx b/src/views/TagDetail/Articles/index.tsx index 9c6ed7ee03..9ef95e2a45 100644 --- a/src/views/TagDetail/Articles/index.tsx +++ b/src/views/TagDetail/Articles/index.tsx @@ -166,13 +166,6 @@ const TagDetailArticles = ({ tag, feedType }: TagArticlesProps) => { return } - const isEditor = _some( - tag?.editors || [], - (editor) => editor.id === viewer.id - ) - const isCreator = tag?.creator?.id === viewer.id - const canEditTag = isEditor || isCreator || viewer.isAdmin - return ( { }} tagDetailId={tag.id} hasEdit={true} - hasSetTagSelected={canEditTag && !isSelected} - hasSetTagUnselected={canEditTag && isSelected} - hasRemoveTag={canEditTag} hasArchive={true} /> From 6db96f9f2bf035efb36416cb881a06b725568096 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:04:10 +0800 Subject: [PATCH 16/69] feat(TagDetail): revise RelatedTags --- lang/default.json | 3 - lang/en.json | 3 - lang/zh-Hans.json | 3 - lang/zh-Hant.json | 3 - src/views/TagDetail/RelatedTags/index.tsx | 122 +++--------------- .../TagDetail/RelatedTags/styles.module.css | 36 ++++-- 6 files changed, 45 insertions(+), 125 deletions(-) diff --git a/lang/default.json b/lang/default.json index c133d95dbe..1653349e3a 100644 --- a/lang/default.json +++ b/lang/default.json @@ -2963,9 +2963,6 @@ "defaultMessage": "Invalid Email", "description": "USER_EMAIL_INVALID" }, - "o2Na0B": { - "defaultMessage": "Back to All" - }, "oGiO//": { "defaultMessage": "Insert audio" }, diff --git a/lang/en.json b/lang/en.json index e3544b6527..0f1ae811cc 100644 --- a/lang/en.json +++ b/lang/en.json @@ -2963,9 +2963,6 @@ "defaultMessage": "Invalid Email", "description": "USER_EMAIL_INVALID" }, - "o2Na0B": { - "defaultMessage": "Back to All" - }, "oGiO//": { "defaultMessage": "Insert audio" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index d3fd7fd9f6..d26c7753d9 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -2963,9 +2963,6 @@ "defaultMessage": "邮箱不正确", "description": "USER_EMAIL_INVALID" }, - "o2Na0B": { - "defaultMessage": "返回全部" - }, "oGiO//": { "defaultMessage": "插入音频" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index e0bb561f8e..e110cfd0e3 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -2963,9 +2963,6 @@ "defaultMessage": "電子信箱不正確", "description": "USER_EMAIL_INVALID" }, - "o2Na0B": { - "defaultMessage": "返回全部" - }, "oGiO//": { "defaultMessage": "插入音訊" }, diff --git a/src/views/TagDetail/RelatedTags/index.tsx b/src/views/TagDetail/RelatedTags/index.tsx index 61d19fc4f9..be3858032a 100644 --- a/src/views/TagDetail/RelatedTags/index.tsx +++ b/src/views/TagDetail/RelatedTags/index.tsx @@ -5,18 +5,8 @@ import _get from 'lodash/get' import _random from 'lodash/random' import { FormattedMessage } from 'react-intl' -import { PATHS } from '~/common/enums' import { analytics } from '~/common/utils' -import { - List, - PageHeader, - ShuffleButton, - Slides, - TagDigest, - usePublicQuery, - ViewAllButton, - ViewMoreCard, -} from '~/components' +import { ArticleTag, usePublicQuery } from '~/components' import FETCH_RECORD from '~/components/GQL/queries/lastFetchRandom' import { LastFetchRandomQuery, TagDetailRecommendedQuery } from '~/gql/graphql' @@ -28,49 +18,29 @@ interface RelatedTagsProps { inSidebar?: boolean } -const RelatedTagsHeader = ({ - hasViewAll, - hasShuffle, - onShuffle, -}: { - hasViewAll?: boolean - hasShuffle?: boolean - onShuffle?: () => void -}) => { +const RelatedTagsHeader = () => { return ( - - } - is="h2" - hasBorder={false} - > -
    - {hasShuffle && } - {hasViewAll && } -
    -
    +
    + +
    ) } const RelatedTags: React.FC = ({ tagId, inSidebar }) => { - const { data: lastFetchRandom, client } = useQuery( + const { data: lastFetchRandom } = useQuery( FETCH_RECORD, { variables: { id: 'local' } } ) const lastRandom = lastFetchRandom?.lastFetchRandom.feedTags - const { data, refetch } = usePublicQuery( - RELATED_TAGS, - { - variables: { id: tagId, random: lastRandom || 0 }, - } - ) + const { data } = usePublicQuery(RELATED_TAGS, { + variables: { id: tagId, random: lastRandom || 0 }, + }) const { edges } = (data?.node?.__typename === 'Tag' && data.node.recommended) || {} @@ -87,73 +57,23 @@ const RelatedTags: React.FC = ({ tagId, inSidebar }) => { return null } - const shuffle = () => { - const random = _random(0, 49) - refetch({ random }) - - client.writeData({ - id: 'LastFetchRandom:local', - data: { feedAuthors: random }, - }) - } - const relatedTagsClasses = classNames({ [styles.relatedTags]: true, [styles.inSidebar]: inSidebar, }) - if (!inSidebar) { - return ( -
    - }> - {_chunk(edges, 5).map((chunks, edgeIndex) => ( - -
    - {chunks.map(({ node, cursor }, nodeIndex) => ( - - trackRelatedTags( - (edgeIndex + 1) * (nodeIndex + 1) - 1, - node.id - ) - } - /> - ))} -
    -
    - ))} -
    - -
    - - - -
    -
    - ) - } - return (
    - - + +
    {edges?.map(({ node, cursor }, i) => ( - - trackRelatedTags(i, node.id)} - /> - + trackRelatedTags(i, node.id)} + /> ))} - +
    ) } diff --git a/src/views/TagDetail/RelatedTags/styles.module.css b/src/views/TagDetail/RelatedTags/styles.module.css index 8c29e8ba0d..65ef5cf989 100644 --- a/src/views/TagDetail/RelatedTags/styles.module.css +++ b/src/views/TagDetail/RelatedTags/styles.module.css @@ -1,21 +1,33 @@ .relatedTags { - border-top: 1px dashed var(--color-grey-lighter); - border-bottom: 1px dashed var(--color-grey-lighter); - - & :global(.list-item > .card) { - margin: 0 calc(var(--sp8) * -1); - } + padding-bottom: var(--sp24); + margin-top: var(--sp24); + border-bottom: 1px dashed var(--color-grey-light); } .inSidebar { - border-top-width: 0; - border-bottom-width: 0; + padding-bottom: 0; + margin-top: 0; + border-bottom: none; +} + +.header { + margin-bottom: var(--sp18); + font-size: var(--text14); + font-weight: var(--font-medium); + line-height: 1.375rem; + color: var(--color-black); + + @media (--sm-up) { + margin-bottom: var(--sp16); + } } -.right { - @mixin flex-center-all; +.tags { + display: flex; + flex-wrap: wrap; + gap: var(--sp8); - & > * + * { - margin-left: var(--sp16); + @media (--sm-up) { + gap: var(--sp16); } } From c868e07ec25c0d39f6ba31183922b512ec2fbfa6 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:07:47 +0700 Subject: [PATCH 17/69] feat(tag): retire unused tag management features --- lang/default.json | 133 --------- lang/en.json | 133 --------- lang/zh-Hans.json | 133 --------- lang/zh-Hant.json | 133 --------- src/common/enums/oauth.ts | 28 +- .../DropdownActions/ArchiveArticle/Dialog.tsx | 2 - .../DropdownActions/RemoveTagButton.tsx | 86 ------ .../DropdownActions/SetTagSelectedButton.tsx | 81 ----- .../SetTagUnselectedButton.tsx | 129 -------- .../ArticleDigest/DropdownActions/gql.ts | 9 - .../ArticleDigest/DropdownActions/index.tsx | 13 - src/components/ArticleDigest/Feed/index.tsx | 2 +- .../Buttons/Bookmark/Bookmark.test.tsx | 4 +- src/components/Buttons/Bookmark/Subscribe.tsx | 8 +- .../Buttons/Bookmark/Unsubscribe.tsx | 8 +- src/components/Buttons/Bookmark/index.tsx | 4 +- .../Dialogs/EditTagDialog/Content.tsx | 223 -------------- .../Dialogs/EditTagDialog/index.tsx | 44 --- .../Dialogs/EditTagDialog/styles.module.css | 7 - .../Dialogs/TagAdoptionDialog/index.tsx | 112 ------- .../Dialogs/TagEditorDialog/List/index.tsx | 200 ------------- .../TagEditorDialog/List/styles.module.css | 3 - .../Dialogs/TagEditorDialog/Remove/index.tsx | 127 -------- .../TagEditorDialog/Remove/styles.module.css | 4 - .../TagEditorDialog/SearchSelect/index.tsx | 151 ---------- .../Dialogs/TagEditorDialog/index.tsx | 101 ------- .../Dialogs/TagLeaveDialog/index.tsx | 105 ------- src/components/Dialogs/index.tsx | 6 - src/components/GQL/fragments/tag.ts | 22 +- .../GQL/mutations/addArticlesTags.ts | 14 - src/components/GQL/mutations/changeEmail.ts | 12 - .../GQL/mutations/toggleBookmarkArticle.ts | 10 + .../GQL/mutations/toggleBookmarkTag.ts | 10 + .../GQL/mutations/toggleFollowTag.ts | 10 - .../GQL/mutations/toggleSubscribeArticle.ts | 10 - .../GQL/mutations/updateTagSetting.ts | 29 -- src/components/GQL/queries/tagArticles.ts | 10 +- src/components/GQL/queries/tagFollowers.ts | 15 - src/components/GQL/queries/tagMaintainers.ts | 23 -- src/components/GQL/queries/walletBalance.ts | 1 - src/components/GQL/updates/index.ts | 2 - src/components/GQL/updates/tagFollowers.ts | 68 ----- src/components/GQL/updates/tagMaintainers.ts | 64 ---- .../TagDigest/Buttons/FollowButton/Follow.tsx | 8 +- .../Buttons/FollowButton/Unfollow.tsx | 39 +-- src/components/TagDigest/Rich/Rich.test.tsx | 2 +- src/components/TagDigest/Rich/index.tsx | 9 - src/components/TagDigest/Sidebar/index.tsx | 4 +- .../components/ArticleDigest/Feed.stories.tsx | 4 +- .../components/TagDigest/Rich.stories.tsx | 1 - src/stories/mocks/index.ts | 2 +- .../Feed/DropdownActions/UnfollowTag.tsx | 46 +-- src/views/Home/Sidebar/Tags/index.tsx | 3 +- src/views/Me/Wallet/Balance/LikeCoin.tsx | 1 - src/views/TagDetail/Articles/index.tsx | 10 - .../TagDetail/Buttons/FollowButton/Follow.tsx | 17 +- .../Buttons/FollowButton/Unfollow.tsx | 47 ++- .../TagDetail/Community/Maintainers/index.tsx | 125 -------- .../TagDetail/Community/Participants/gql.ts | 29 -- .../Community/Participants/index.tsx | 110 ------- src/views/TagDetail/Community/index.tsx | 21 -- .../TagDetail/Community/styles.module.css | 12 - src/views/TagDetail/Cover/index.tsx | 64 ---- src/views/TagDetail/Cover/styles.module.css | 51 ---- src/views/TagDetail/DropdownActions/index.tsx | 278 ------------------ .../DropdownActions/styles.module.css | 3 - src/views/TagDetail/Followers/index.tsx | 39 --- .../TagDetail/Followers/styles.module.css | 15 - src/views/TagDetail/Owner/index.tsx | 103 ------- src/views/TagDetail/Owner/styles.module.css | 20 -- src/views/TagDetail/gql.ts | 23 +- src/views/TagDetail/index.tsx | 63 +--- .../FollowingDialog/TagsFeed/index.tsx | 1 - tests/helpers/poms/articleDetail.ts | 2 +- 74 files changed, 112 insertions(+), 3329 deletions(-) delete mode 100644 src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx delete mode 100644 src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx delete mode 100644 src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx delete mode 100644 src/components/Dialogs/EditTagDialog/Content.tsx delete mode 100644 src/components/Dialogs/EditTagDialog/index.tsx delete mode 100644 src/components/Dialogs/EditTagDialog/styles.module.css delete mode 100644 src/components/Dialogs/TagAdoptionDialog/index.tsx delete mode 100644 src/components/Dialogs/TagEditorDialog/List/index.tsx delete mode 100644 src/components/Dialogs/TagEditorDialog/List/styles.module.css delete mode 100644 src/components/Dialogs/TagEditorDialog/Remove/index.tsx delete mode 100644 src/components/Dialogs/TagEditorDialog/Remove/styles.module.css delete mode 100644 src/components/Dialogs/TagEditorDialog/SearchSelect/index.tsx delete mode 100644 src/components/Dialogs/TagEditorDialog/index.tsx delete mode 100644 src/components/Dialogs/TagLeaveDialog/index.tsx delete mode 100644 src/components/GQL/mutations/addArticlesTags.ts delete mode 100644 src/components/GQL/mutations/changeEmail.ts create mode 100644 src/components/GQL/mutations/toggleBookmarkArticle.ts create mode 100644 src/components/GQL/mutations/toggleBookmarkTag.ts delete mode 100644 src/components/GQL/mutations/toggleFollowTag.ts delete mode 100644 src/components/GQL/mutations/toggleSubscribeArticle.ts delete mode 100644 src/components/GQL/mutations/updateTagSetting.ts delete mode 100644 src/components/GQL/queries/tagFollowers.ts delete mode 100644 src/components/GQL/queries/tagMaintainers.ts delete mode 100644 src/components/GQL/updates/tagFollowers.ts delete mode 100644 src/components/GQL/updates/tagMaintainers.ts delete mode 100644 src/views/TagDetail/Community/Maintainers/index.tsx delete mode 100644 src/views/TagDetail/Community/Participants/gql.ts delete mode 100644 src/views/TagDetail/Community/Participants/index.tsx delete mode 100644 src/views/TagDetail/Community/index.tsx delete mode 100644 src/views/TagDetail/Community/styles.module.css delete mode 100644 src/views/TagDetail/Cover/index.tsx delete mode 100644 src/views/TagDetail/Cover/styles.module.css delete mode 100644 src/views/TagDetail/DropdownActions/index.tsx delete mode 100644 src/views/TagDetail/DropdownActions/styles.module.css delete mode 100644 src/views/TagDetail/Followers/index.tsx delete mode 100644 src/views/TagDetail/Followers/styles.module.css delete mode 100644 src/views/TagDetail/Owner/index.tsx delete mode 100644 src/views/TagDetail/Owner/styles.module.css diff --git a/lang/default.json b/lang/default.json index 5e67b3d6ea..320b760aaa 100644 --- a/lang/default.json +++ b/lang/default.json @@ -127,15 +127,9 @@ "0/gRer": { "defaultMessage": "I am migrating to Matters, and I invite you to come along" }, - "0/iEw/": { - "defaultMessage": "Manage Communities" - }, "06XHBC": { "defaultMessage": "Add to Circle" }, - "0Azlrb": { - "defaultMessage": "Manage" - }, "0CyECR": { "defaultMessage": "Matters ID has been set up. More account info can be found in Settings", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" @@ -228,9 +222,6 @@ "defaultMessage": "No data yet", "description": "src/views/Me/History/index.tsx" }, - "1ZFwRz": { - "defaultMessage": "Confirm Removal" - }, "1exrSw": { "defaultMessage": "Welcome onboard!" }, @@ -343,9 +334,6 @@ "3YAasP": { "defaultMessage": "What is Liker ID?" }, - "3fqQHv": { - "defaultMessage": "Add tag editor" - }, "3kbIhS": { "defaultMessage": "Untitled" }, @@ -416,9 +404,6 @@ "defaultMessage": "Do you want to disconnect from {type}?", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, - "5FO4vn": { - "defaultMessage": "You do not have permission to perform this operation" - }, "5Ga0iK": { "defaultMessage": "Insert code" }, @@ -480,10 +465,6 @@ "62nsdy": { "defaultMessage": "Retry" }, - "63HuBz": { - "defaultMessage": "This tag has no manager currently", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "69+D96": { "defaultMessage": "Start Creating" }, @@ -609,10 +590,6 @@ "7oytv9": { "defaultMessage": "(edited)" }, - "7xnrxG": { - "defaultMessage": "The article has been added to the Trending", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "7ykJ+l": { "defaultMessage": "Still quiet here. {br}Be the first one to say hello!", "description": "src/components/Empty/EmptyComment.tsx" @@ -766,10 +743,6 @@ "AGDFGs": { "defaultMessage": "Discrimination, insult, or hatred" }, - "ANA7sk": { - "defaultMessage": "Maintain", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "AVpR3Q": { "defaultMessage": "Wallet linked", "description": "src/components/UserProfile/WalletLabel/index.tsx" @@ -1102,10 +1075,6 @@ "GRrsEH": { "defaultMessage": "View published article" }, - "GRtGnZ": { - "defaultMessage": "Resign From Maintainer", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "GU6vV0": { "defaultMessage": "No collection created yet", "description": "src/components/Empty/EmptyCollection.tsx" @@ -1193,9 +1162,6 @@ "Hlwud7": { "defaultMessage": "More ENS information, check {node}." }, - "Hm2DAQ": { - "defaultMessage": "Confirm collaborator removal" - }, "HnxG15": { "defaultMessage": "Set" }, @@ -1301,10 +1267,6 @@ "Jr12wo": { "defaultMessage": "Insert video" }, - "Js/Fij": { - "defaultMessage": "This article has been removed from Trending", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "Jxr/TM": { "defaultMessage": "FULL", "description": "src/components/Dialogs/AddCollectionsArticleDialog/SelectDialogContent.tsx" @@ -1330,10 +1292,6 @@ "defaultMessage": "Circle successfully created", "description": "src/components/Forms/CreateCircleForm/Profile.tsx" }, - "KMcrz8": { - "defaultMessage": "Maintain Tag", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "KQi/UZ": { "defaultMessage": "Archive works" }, @@ -1348,9 +1306,6 @@ "defaultMessage": "Wallet connected", "description": "src/components/Forms/WalletAuthForm/Connect.tsx" }, - "KoR0wt": { - "defaultMessage": "Collaborator can manage selected feed with you." - }, "Kwv1n3": { "defaultMessage": "registration is about 1 LIKE. During promotion period it is sponsored by Matters.News." }, @@ -1377,10 +1332,6 @@ "defaultMessage": "Expand", "description": "src/components/Expandable/index.tsx" }, - "L7Si5/": { - "defaultMessage": "Manage Community", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "LETb4b": { "defaultMessage": "Collections allow up to {count} articles currently", "description": "src/views/User/CollectionDetail/CollectionArticles/ViewerArticles.tsx" @@ -1423,9 +1374,6 @@ "defaultMessage": "You do not have permissionn to perform this operation", "description": "FORBIDDEN_BY_TARGET_STATE" }, - "LnesNr": { - "defaultMessage": "Successfully removed collaborator" - }, "LoQ3BF": { "defaultMessage": "This badge represents your completion of Free Write in 7 days. Congratulations on finishing this meaningful writing journey!" }, @@ -1602,12 +1550,6 @@ "defaultMessage": "guide", "description": "src/components/Forms/PaymentForm/PayTo/SetAmount/SetAmountHeader/WhyOptimismDialog/index.tsx" }, - "P1AKC5": { - "defaultMessage": "Collaborator" - }, - "P2Btra": { - "defaultMessage": "Adopted" - }, "P3y9Bo": { "defaultMessage": "Go to sign", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -1693,9 +1635,6 @@ "QvPc1q": { "defaultMessage": "Upload Cover" }, - "Qzdtxi": { - "defaultMessage": "Resign as tag maintainer" - }, "R410ei": { "defaultMessage": "Incorrect verification code", "description": "CODE_INVALID" @@ -1830,9 +1769,6 @@ "T9oZC8": { "defaultMessage": "Are you sure you want to delete this collection ‘{collection}’?" }, - "TAPLOf": { - "defaultMessage": "Every tag can have maximum {count} collaborators." - }, "TF1OhT": { "defaultMessage": "This login code has expired, please try to resend" }, @@ -1863,9 +1799,6 @@ "defaultMessage": "Optimism is a standalone blockchain. If you have USDT on other chains, you need to transfer them to Optimism. See details in the {tutorial}.", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" }, - "ThSfXQ": { - "defaultMessage": "Successfully added collaborator" - }, "TjWWxF": { "defaultMessage": "Broadcast sent", "description": "src/views/Circle/Broadcast/Broadcast.tsx" @@ -1910,10 +1843,6 @@ "defaultMessage": "Move to bottom", "description": "src/components/ArticleDigest/DropdownActions/SetBottomCollectionButton.tsx" }, - "UjKkhq": { - "defaultMessage": "Tags added", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "Up5U7K": { "defaultMessage": "Block" }, @@ -1924,9 +1853,6 @@ "Uq6tfM": { "defaultMessage": "Add caption…" }, - "Uv0hqn": { - "defaultMessage": "Adopt Tag" - }, "UxAA/V": { "defaultMessage": "Optimism is a Layer 2 scaling solution based on Ethereum that can provide faster and cheaper transactions, while ensuring security, making it easier for you to support creators.", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2014,10 +1940,6 @@ "WQT8ZA": { "defaultMessage": "Edit collection" }, - "WSUAwk": { - "defaultMessage": "Add to Featured", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "WiGHyF": { "defaultMessage": "Web Monetization standard" }, @@ -2217,9 +2139,6 @@ "defaultMessage": "Number of readers: unique registered users plus number of anonymous IP addresses visited the article (Data will be updated periodically and may be delayed)", "description": "src/views/Me/Works/Published/SortTabs.tsx" }, - "a3j20X": { - "defaultMessage": "Maintain immediately" - }, "aCTmEO": { "defaultMessage": "I don't have a wallet yet", "description": "src/components/Forms/SelectAuthMethodForm/WalletFeed.tsx" @@ -2235,9 +2154,6 @@ "aKEiNd": { "defaultMessage": "You missed the registration period, you can still join as a latecomer. Apply earlier next time for the chance to get the badge." }, - "aKlTO2": { - "defaultMessage": "You can add {count} more collaborators." - }, "aOFCqL": { "defaultMessage": "Most comments", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2248,10 +2164,6 @@ "aTmmkr": { "defaultMessage": "You have unsubscribed the circle." }, - "aa0nss": { - "defaultMessage": "Unpin from Trending", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "aaUBvF": { "defaultMessage": "comment_circle", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" @@ -2409,9 +2321,6 @@ "deEeEI": { "defaultMessage": "Register" }, - "dg3JCQ": { - "defaultMessage": "collaborators" - }, "djJp6c": { "defaultMessage": "History" }, @@ -2438,9 +2347,6 @@ "eWXgsZ": { "defaultMessage": "Clear Content" }, - "eXDZGQ": { - "defaultMessage": "Maintainer" - }, "eY3YIa": { "defaultMessage": "Copy comment" }, @@ -2591,10 +2497,6 @@ "defaultMessage": "Insufficient:", "description": "src/components/Balance/index.tsx" }, - "hYG5fb": { - "defaultMessage": "are following", - "description": "src/views/TagDetail/Followers/index.tsx" - }, "hgtWIO": { "defaultMessage": "Articles have been collected", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2696,9 +2598,6 @@ "defaultMessage": "broadcast in {circlename}", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, - "k0ooDW": { - "defaultMessage": "Tag Description" - }, "k2veDA": { "defaultMessage": "Write" }, @@ -2715,9 +2614,6 @@ "kCPl0r": { "defaultMessage": "Collect" }, - "kCp8A9": { - "defaultMessage": "After resignation, you will not be able to manage tags." - }, "kEDrXh": { "defaultMessage": "liked your collection" }, @@ -2796,9 +2692,6 @@ "lIir/P": { "defaultMessage": "I see" }, - "lMKb5N": { - "defaultMessage": "Resignation Success" - }, "lNWFnL": { "defaultMessage": "Share this article in translated version" }, @@ -2809,9 +2702,6 @@ "lO7wKc": { "defaultMessage": "Not yet" }, - "lT6Dt8": { - "defaultMessage": "Confirm Resignation" - }, "lZukEr": { "defaultMessage": "commented", "description": "src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx" @@ -2931,9 +2821,6 @@ "defaultMessage": "replied your comment in", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, - "nNLkZ8": { - "defaultMessage": "Add collaborator" - }, "nWhqw9": { "defaultMessage": "Publish Now" }, @@ -3074,10 +2961,6 @@ "qhVSGI": { "defaultMessage": "Hmm... It seems the author has hidden this work. Go see something else" }, - "qlki7w": { - "defaultMessage": "Remove Article", - "description": "src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx" - }, "qlxeW+": { "defaultMessage": "Undo downvote" }, @@ -3120,9 +3003,6 @@ "defaultMessage": "Edit", "description": "src/components/Dialogs/ReviseArticleDialog/index.tsx" }, - "rLlTQ9": { - "defaultMessage": "Tag Name" - }, "rXnmeE": { "defaultMessage": "Confirm and Send" }, @@ -3240,9 +3120,6 @@ "defaultMessage": "Comment has been deleted", "description": "Moment" }, - "uJkv2X": { - "defaultMessage": "Edit Tag" - }, "uM5qZr": { "defaultMessage": "Likes Given" }, @@ -3336,9 +3213,6 @@ "defaultMessage": "supported", "description": "src/components/Notice/TransactionNotice/PaymentReceivedDonationNotice.tsx" }, - "vLcHiG": { - "defaultMessage": "After removal, {user} user will not be able to manage selected feed." - }, "vRCDr8": { "defaultMessage": "You can quickly log in to your account after binding.{br}Readers can also freely transfer money through other channels to support you!", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -3508,10 +3382,6 @@ "yOhatg": { "defaultMessage": "Other malicious behavior" }, - "ySGgTo": { - "defaultMessage": "Add Articles into Featured", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "ySSF/a": { "defaultMessage": "In order to ensure the identity security of the citizens of Matters City, we've upgraded some security settings. Please confirm your Matters ID (cannot be modified once confirmation).", "description": "src/components/Dialogs/SetUserNameDialog/Content.tsx" @@ -3520,9 +3390,6 @@ "defaultMessage": "Please refresh the page and try again.", "description": "NETWORK_ERROR" }, - "yXWwSW": { - "defaultMessage": "Are you sure 😭" - }, "yZfKI4": { "defaultMessage": "discussion and mentioned you", "description": "src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx" diff --git a/lang/en.json b/lang/en.json index 42e5229aa7..a7068ee251 100644 --- a/lang/en.json +++ b/lang/en.json @@ -127,15 +127,9 @@ "0/gRer": { "defaultMessage": "I am migrating to Matters, and I invite you to come along" }, - "0/iEw/": { - "defaultMessage": "Manage Communities" - }, "06XHBC": { "defaultMessage": "Add to Circle" }, - "0Azlrb": { - "defaultMessage": "Manage" - }, "0CyECR": { "defaultMessage": "Matters ID has been set up. More account info can be found in Settings", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" @@ -228,9 +222,6 @@ "defaultMessage": "No data yet", "description": "src/views/Me/History/index.tsx" }, - "1ZFwRz": { - "defaultMessage": "Confirm Removal" - }, "1exrSw": { "defaultMessage": "Welcome onboard!" }, @@ -343,9 +334,6 @@ "3YAasP": { "defaultMessage": "What is Liker ID?" }, - "3fqQHv": { - "defaultMessage": "Add tag editor" - }, "3kbIhS": { "defaultMessage": "Untitled" }, @@ -416,9 +404,6 @@ "defaultMessage": "Do you want to disconnect from {type}?", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, - "5FO4vn": { - "defaultMessage": "You do not have permission to perform this operation" - }, "5Ga0iK": { "defaultMessage": "Insert code" }, @@ -480,10 +465,6 @@ "62nsdy": { "defaultMessage": "Retry" }, - "63HuBz": { - "defaultMessage": "This tag has no manager currently", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "69+D96": { "defaultMessage": "Start Creating" }, @@ -609,10 +590,6 @@ "7oytv9": { "defaultMessage": " (edited) " }, - "7xnrxG": { - "defaultMessage": "The article has been added to the Trending", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "7ykJ+l": { "defaultMessage": "Still quiet here. {br}Be the first one to say hello!", "description": "src/components/Empty/EmptyComment.tsx" @@ -766,10 +743,6 @@ "AGDFGs": { "defaultMessage": "Discrimination, insult, or hatred" }, - "ANA7sk": { - "defaultMessage": "Maintain", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "AVpR3Q": { "defaultMessage": "Wallet linked", "description": "src/components/UserProfile/WalletLabel/index.tsx" @@ -1102,10 +1075,6 @@ "GRrsEH": { "defaultMessage": "View published article" }, - "GRtGnZ": { - "defaultMessage": "Resign From Maintainer", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "GU6vV0": { "defaultMessage": "No collection created yet", "description": "src/components/Empty/EmptyCollection.tsx" @@ -1193,9 +1162,6 @@ "Hlwud7": { "defaultMessage": "More ENS information, check {node}." }, - "Hm2DAQ": { - "defaultMessage": "Confirm collaborator removal" - }, "HnxG15": { "defaultMessage": "Set" }, @@ -1301,10 +1267,6 @@ "Jr12wo": { "defaultMessage": "Insert video" }, - "Js/Fij": { - "defaultMessage": "This article has been removed from Trending", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "Jxr/TM": { "defaultMessage": "FULL", "description": "src/components/Dialogs/AddCollectionsArticleDialog/SelectDialogContent.tsx" @@ -1330,10 +1292,6 @@ "defaultMessage": "Circle successfully created", "description": "src/components/Forms/CreateCircleForm/Profile.tsx" }, - "KMcrz8": { - "defaultMessage": "Maintain Tag", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "KQi/UZ": { "defaultMessage": "Archive works" }, @@ -1348,9 +1306,6 @@ "defaultMessage": "Wallet connected", "description": "src/components/Forms/WalletAuthForm/Connect.tsx" }, - "KoR0wt": { - "defaultMessage": "Collaborator can manage selected feed with you." - }, "Kwv1n3": { "defaultMessage": " registration is about 1 LIKE. During promotion period it is sponsored by Matters.News." }, @@ -1377,10 +1332,6 @@ "defaultMessage": "Expand", "description": "src/components/Expandable/index.tsx" }, - "L7Si5/": { - "defaultMessage": "Manage Community", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "LETb4b": { "defaultMessage": "Collections allow up to {count} articles currently", "description": "src/views/User/CollectionDetail/CollectionArticles/ViewerArticles.tsx" @@ -1423,9 +1374,6 @@ "defaultMessage": "You do not have permissionn to perform this operation", "description": "FORBIDDEN_BY_TARGET_STATE" }, - "LnesNr": { - "defaultMessage": "Successfully removed collaborator" - }, "LoQ3BF": { "defaultMessage": "This badge represents your completion of Free Write in 7 days. Congratulations on finishing this meaningful writing journey!" }, @@ -1602,12 +1550,6 @@ "defaultMessage": "guide", "description": "src/components/Forms/PaymentForm/PayTo/SetAmount/SetAmountHeader/WhyOptimismDialog/index.tsx" }, - "P1AKC5": { - "defaultMessage": "Collaborator" - }, - "P2Btra": { - "defaultMessage": "Adopted" - }, "P3y9Bo": { "defaultMessage": "Go to sign", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -1693,9 +1635,6 @@ "QvPc1q": { "defaultMessage": "Upload Cover" }, - "Qzdtxi": { - "defaultMessage": "Resign as tag maintainer" - }, "R410ei": { "defaultMessage": "Incorrect verification code", "description": "CODE_INVALID" @@ -1830,9 +1769,6 @@ "T9oZC8": { "defaultMessage": "Are you sure you want to delete this collection ‘{collection}’?" }, - "TAPLOf": { - "defaultMessage": "Every tag can have maximum {count} collaborators." - }, "TF1OhT": { "defaultMessage": "This login code has expired, please try to resend" }, @@ -1863,9 +1799,6 @@ "defaultMessage": "Optimism is a standalone blockchain. If you have USDT on other chains, you need to transfer them to Optimism. See details in the {tutorial}.", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" }, - "ThSfXQ": { - "defaultMessage": "Successfully added collaborator" - }, "TjWWxF": { "defaultMessage": "Broadcast sent", "description": "src/views/Circle/Broadcast/Broadcast.tsx" @@ -1910,10 +1843,6 @@ "defaultMessage": "Move to bottom", "description": "src/components/ArticleDigest/DropdownActions/SetBottomCollectionButton.tsx" }, - "UjKkhq": { - "defaultMessage": "Tags added", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "Up5U7K": { "defaultMessage": "Block" }, @@ -1924,9 +1853,6 @@ "Uq6tfM": { "defaultMessage": "Add caption…" }, - "Uv0hqn": { - "defaultMessage": "Adopt Tag" - }, "UxAA/V": { "defaultMessage": "Optimism is a Layer 2 scaling solution based on Ethereum that can provide faster and cheaper transactions, while ensuring security, making it easier for you to support creators.", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2014,10 +1940,6 @@ "WQT8ZA": { "defaultMessage": "Edit collection" }, - "WSUAwk": { - "defaultMessage": "Add to Featured", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "WiGHyF": { "defaultMessage": "Web Monetization standard" }, @@ -2217,9 +2139,6 @@ "defaultMessage": "Number of readers: unique registered users plus number of anonymous IP addresses visited the article (Data will be updated periodically and may be delayed)", "description": "src/views/Me/Works/Published/SortTabs.tsx" }, - "a3j20X": { - "defaultMessage": "Maintain immediately" - }, "aCTmEO": { "defaultMessage": "I don't have a wallet yet", "description": "src/components/Forms/SelectAuthMethodForm/WalletFeed.tsx" @@ -2235,9 +2154,6 @@ "aKEiNd": { "defaultMessage": "You missed the registration period, you can still join as a latecomer. Apply earlier next time for the chance to get the badge." }, - "aKlTO2": { - "defaultMessage": "You can add {count} more collaborators." - }, "aOFCqL": { "defaultMessage": "Most comments", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2248,10 +2164,6 @@ "aTmmkr": { "defaultMessage": "You have unsubscribed the circle." }, - "aa0nss": { - "defaultMessage": "Unpin from Trending", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "aaUBvF": { "defaultMessage": "comment_circle", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" @@ -2409,9 +2321,6 @@ "deEeEI": { "defaultMessage": "Register" }, - "dg3JCQ": { - "defaultMessage": "collaborators" - }, "djJp6c": { "defaultMessage": "History" }, @@ -2438,9 +2347,6 @@ "eWXgsZ": { "defaultMessage": "Clear Content" }, - "eXDZGQ": { - "defaultMessage": "Maintainer" - }, "eY3YIa": { "defaultMessage": "Copy comment" }, @@ -2591,10 +2497,6 @@ "defaultMessage": "Insufficient: ", "description": "src/components/Balance/index.tsx" }, - "hYG5fb": { - "defaultMessage": "are following", - "description": "src/views/TagDetail/Followers/index.tsx" - }, "hgtWIO": { "defaultMessage": "Articles have been collected", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2696,9 +2598,6 @@ "defaultMessage": "broadcast in {circlename}", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, - "k0ooDW": { - "defaultMessage": "Tag Description" - }, "k2veDA": { "defaultMessage": "Write" }, @@ -2715,9 +2614,6 @@ "kCPl0r": { "defaultMessage": "Collect" }, - "kCp8A9": { - "defaultMessage": "After resignation, you will not be able to manage tags." - }, "kEDrXh": { "defaultMessage": "liked your collection" }, @@ -2796,9 +2692,6 @@ "lIir/P": { "defaultMessage": "I see" }, - "lMKb5N": { - "defaultMessage": "Resignation Success" - }, "lNWFnL": { "defaultMessage": "Share this article in translated version" }, @@ -2809,9 +2702,6 @@ "lO7wKc": { "defaultMessage": "Not yet" }, - "lT6Dt8": { - "defaultMessage": "Confirm Resignation" - }, "lZukEr": { "defaultMessage": "commented", "description": "src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx" @@ -2931,9 +2821,6 @@ "defaultMessage": "replied your comment in", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, - "nNLkZ8": { - "defaultMessage": "Add collaborator" - }, "nWhqw9": { "defaultMessage": "Publish Now" }, @@ -3074,10 +2961,6 @@ "qhVSGI": { "defaultMessage": "Hmm... It seems the author has hidden this work. Go see something else" }, - "qlki7w": { - "defaultMessage": "Remove Article", - "description": "src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx" - }, "qlxeW+": { "defaultMessage": "Undo downvote" }, @@ -3120,9 +3003,6 @@ "defaultMessage": "Edit", "description": "src/components/Dialogs/ReviseArticleDialog/index.tsx" }, - "rLlTQ9": { - "defaultMessage": "Tag Name" - }, "rXnmeE": { "defaultMessage": "Confirm and Send" }, @@ -3240,9 +3120,6 @@ "defaultMessage": "Comment has been deleted", "description": "Moment" }, - "uJkv2X": { - "defaultMessage": "Edit Tag" - }, "uM5qZr": { "defaultMessage": "Likes Given" }, @@ -3336,9 +3213,6 @@ "defaultMessage": "supported", "description": "src/components/Notice/TransactionNotice/PaymentReceivedDonationNotice.tsx" }, - "vLcHiG": { - "defaultMessage": "After removal, {user} user will not be able to manage selected feed." - }, "vRCDr8": { "defaultMessage": "You can quickly log in to your account after binding.{br}Readers can also freely transfer money through other channels to support you!", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -3508,10 +3382,6 @@ "yOhatg": { "defaultMessage": "Other malicious behavior" }, - "ySGgTo": { - "defaultMessage": "Add Articles into Featured", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "ySSF/a": { "defaultMessage": "In order to ensure the identity security of the citizens of Matters City, we've upgraded some security settings. Please confirm your Matters ID (cannot be modified once confirmation).", "description": "src/components/Dialogs/SetUserNameDialog/Content.tsx" @@ -3520,9 +3390,6 @@ "defaultMessage": "Please refresh the page and try again.", "description": "NETWORK_ERROR" }, - "yXWwSW": { - "defaultMessage": "Are you sure 😭" - }, "yZfKI4": { "defaultMessage": "discussion and mentioned you", "description": "src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 49213a590e..a8f4d97d20 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -127,15 +127,9 @@ "0/gRer": { "defaultMessage": "我正在搬家到 Matters,邀请你一起来" }, - "0/iEw/": { - "defaultMessage": "管理社群" - }, "06XHBC": { "defaultMessage": "加入围炉" }, - "0Azlrb": { - "defaultMessage": "管理" - }, "0CyECR": { "defaultMessage": "Matters ID 已设置,更多帐号相关设置可前往设置页修改", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" @@ -228,9 +222,6 @@ "defaultMessage": "尚无阅读记录", "description": "src/views/Me/History/index.tsx" }, - "1ZFwRz": { - "defaultMessage": "确认移除" - }, "1exrSw": { "defaultMessage": "欢迎上船!" }, @@ -343,9 +334,6 @@ "3YAasP": { "defaultMessage": "什么是 Liker ID?" }, - "3fqQHv": { - "defaultMessage": "添加协作者" - }, "3kbIhS": { "defaultMessage": "未命名" }, @@ -416,9 +404,6 @@ "defaultMessage": "确认要解绑 {type} 吗?", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, - "5FO4vn": { - "defaultMessage": "你尚无权限进行该操作" - }, "5Ga0iK": { "defaultMessage": "插入代码" }, @@ -480,10 +465,6 @@ "62nsdy": { "defaultMessage": "重试" }, - "63HuBz": { - "defaultMessage": "此标签目前无人主理", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "69+D96": { "defaultMessage": "开始创作" }, @@ -609,10 +590,6 @@ "7oytv9": { "defaultMessage": "(修改过)" }, - "7xnrxG": { - "defaultMessage": "作品已添加至精选", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "7ykJ+l": { "defaultMessage": "暂无评论", "description": "src/components/Empty/EmptyComment.tsx" @@ -766,10 +743,6 @@ "AGDFGs": { "defaultMessage": "歧视、侮辱或仇恨" }, - "ANA7sk": { - "defaultMessage": "主理", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "AVpR3Q": { "defaultMessage": "已绑定钱包", "description": "src/components/UserProfile/WalletLabel/index.tsx" @@ -1102,10 +1075,6 @@ "GRrsEH": { "defaultMessage": "查看作品" }, - "GRtGnZ": { - "defaultMessage": "辞去权限", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "GU6vV0": { "defaultMessage": "尚未创建选集", "description": "src/components/Empty/EmptyCollection.tsx" @@ -1193,9 +1162,6 @@ "Hlwud7": { "defaultMessage": "更多 ENS 资讯请参考 {node}." }, - "Hm2DAQ": { - "defaultMessage": "确定移除协作者" - }, "HnxG15": { "defaultMessage": "设定" }, @@ -1301,10 +1267,6 @@ "Jr12wo": { "defaultMessage": "插入视频" }, - "Js/Fij": { - "defaultMessage": "作品已取消精选", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "Jxr/TM": { "defaultMessage": "已满", "description": "src/components/Dialogs/AddCollectionsArticleDialog/SelectDialogContent.tsx" @@ -1330,10 +1292,6 @@ "defaultMessage": "围炉创建成功", "description": "src/components/Forms/CreateCircleForm/Profile.tsx" }, - "KMcrz8": { - "defaultMessage": "认领", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "KQi/UZ": { "defaultMessage": "归档作品" }, @@ -1348,9 +1306,6 @@ "defaultMessage": "钱包已绑定", "description": "src/components/Forms/WalletAuthForm/Connect.tsx" }, - "KoR0wt": { - "defaultMessage": "协作者可以与你共同管理精选" - }, "Kwv1n3": { "defaultMessage": " 用以出版 Writing NFT,费用 ≈1 LIKE,推广期由平台补助" }, @@ -1377,10 +1332,6 @@ "defaultMessage": "展开", "description": "src/components/Expandable/index.tsx" }, - "L7Si5/": { - "defaultMessage": "管理社群", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "LETb4b": { "defaultMessage": "选集暂时不允许超过 {count} 篇", "description": "src/views/User/CollectionDetail/CollectionArticles/ViewerArticles.tsx" @@ -1423,9 +1374,6 @@ "defaultMessage": "你无法对此对象进行该操作", "description": "FORBIDDEN_BY_TARGET_STATE" }, - "LnesNr": { - "defaultMessage": "移除协作者成功" - }, "LoQ3BF": { "defaultMessage": "这枚徽章代表你完成了七天写作,恭喜走完这趟意义非凡的写作之旅!" }, @@ -1602,12 +1550,6 @@ "defaultMessage": "教学指南", "description": "src/components/Forms/PaymentForm/PayTo/SetAmount/SetAmountHeader/WhyOptimismDialog/index.tsx" }, - "P1AKC5": { - "defaultMessage": "协作者" - }, - "P2Btra": { - "defaultMessage": "认领成功" - }, "P3y9Bo": { "defaultMessage": "前往签署", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -1693,9 +1635,6 @@ "QvPc1q": { "defaultMessage": "上传封面" }, - "Qzdtxi": { - "defaultMessage": "辞去权限" - }, "R410ei": { "defaultMessage": "验证码错误", "description": "CODE_INVALID" @@ -1830,9 +1769,6 @@ "T9oZC8": { "defaultMessage": "确认要删除该选集“{collection}”吗?" }, - "TAPLOf": { - "defaultMessage": "每个标签最多添加 {count} 名协作者" - }, "TF1OhT": { "defaultMessage": "临时密码已过期,请尝试重新发送" }, @@ -1863,9 +1799,6 @@ "defaultMessage": "Optimism 是独立运行的区块链,若你在其他链上已有 USDT 货币,需要将它们转移到 Optimism 网络才能使用,详情参考 {tutorial}.", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" }, - "ThSfXQ": { - "defaultMessage": "添加协作者成功" - }, "TjWWxF": { "defaultMessage": "广播已送出", "description": "src/views/Circle/Broadcast/Broadcast.tsx" @@ -1910,10 +1843,6 @@ "defaultMessage": "移至底部", "description": "src/components/ArticleDigest/DropdownActions/SetBottomCollectionButton.tsx" }, - "UjKkhq": { - "defaultMessage": "作品已添加标签", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "Up5U7K": { "defaultMessage": "屏蔽" }, @@ -1924,9 +1853,6 @@ "Uq6tfM": { "defaultMessage": "添加说明文字…" }, - "Uv0hqn": { - "defaultMessage": "认领标签" - }, "UxAA/V": { "defaultMessage": "Optimism 是基于以太坊的第二层(Layer2)扩容方案,能提升交易速度,并降低手续费,同时确保安全性,让你更轻松地支持创作者。", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2014,10 +1940,6 @@ "WQT8ZA": { "defaultMessage": "编辑选集" }, - "WSUAwk": { - "defaultMessage": "添加到精选", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "WiGHyF": { "defaultMessage": "Web Monetization 标准" }, @@ -2217,9 +2139,6 @@ "defaultMessage": "读者数量:访问过作品页的不重复的登录用户数加匿名 IP 数(数据周期更新,可能存在延迟)", "description": "src/views/Me/Works/Published/SortTabs.tsx" }, - "a3j20X": { - "defaultMessage": "即刻主理" - }, "aCTmEO": { "defaultMessage": "我还没有钱包", "description": "src/components/Forms/SelectAuthMethodForm/WalletFeed.tsx" @@ -2235,9 +2154,6 @@ "aKEiNd": { "defaultMessage": "错过报名期没关系,仍然可以用晚鸟身份参与,一起书写人生故事。下次早点报名,就有机会获得大满贯徽章!" }, - "aKlTO2": { - "defaultMessage": "你还可以添加 {count} 名协作者" - }, "aOFCqL": { "defaultMessage": "最多评论", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2248,10 +2164,6 @@ "aTmmkr": { "defaultMessage": "你已经与围炉告别,感谢曾经的付出与参与。" }, - "aa0nss": { - "defaultMessage": "取消精选", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "aaUBvF": { "defaultMessage": " 中的发言", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" @@ -2409,9 +2321,6 @@ "deEeEI": { "defaultMessage": "注册" }, - "dg3JCQ": { - "defaultMessage": "协作者" - }, "djJp6c": { "defaultMessage": "我的足跡" }, @@ -2438,9 +2347,6 @@ "eWXgsZ": { "defaultMessage": "清空内容" }, - "eXDZGQ": { - "defaultMessage": "主理人" - }, "eY3YIa": { "defaultMessage": "复制评论" }, @@ -2591,10 +2497,6 @@ "defaultMessage": "余额不足:", "description": "src/components/Balance/index.tsx" }, - "hYG5fb": { - "defaultMessage": "人关注", - "description": "src/views/TagDetail/Followers/index.tsx" - }, "hgtWIO": { "defaultMessage": "作品被关联", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2696,9 +2598,6 @@ "defaultMessage": "在 {circlename} 发布广播", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, - "k0ooDW": { - "defaultMessage": "标签描述" - }, "k2veDA": { "defaultMessage": "创作" }, @@ -2715,9 +2614,6 @@ "kCPl0r": { "defaultMessage": "关联" }, - "kCp8A9": { - "defaultMessage": "如果辞去权限,你将无法继续管理标签。" - }, "kEDrXh": { "defaultMessage": "喜欢你的选集" }, @@ -2796,9 +2692,6 @@ "lIir/P": { "defaultMessage": "我知道了" }, - "lMKb5N": { - "defaultMessage": "辞去权限成功" - }, "lNWFnL": { "defaultMessage": "分享这篇文章的翻译版本" }, @@ -2809,9 +2702,6 @@ "lO7wKc": { "defaultMessage": "再想想" }, - "lT6Dt8": { - "defaultMessage": "确认辞去" - }, "lZukEr": { "defaultMessage": "评论了", "description": "src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx" @@ -2931,9 +2821,6 @@ "defaultMessage": "在 ", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, - "nNLkZ8": { - "defaultMessage": "新增协作者" - }, "nWhqw9": { "defaultMessage": "立即发布" }, @@ -3074,10 +2961,6 @@ "qhVSGI": { "defaultMessage": "呐,作者亲手掩盖了这篇作品的痕迹,看看别的吧" }, - "qlki7w": { - "defaultMessage": "移除作品", - "description": "src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx" - }, "qlxeW+": { "defaultMessage": "取消点踩" }, @@ -3120,9 +3003,6 @@ "defaultMessage": "开始修改", "description": "src/components/Dialogs/ReviseArticleDialog/index.tsx" }, - "rLlTQ9": { - "defaultMessage": "标签名称" - }, "rXnmeE": { "defaultMessage": "确认发送" }, @@ -3240,9 +3120,6 @@ "defaultMessage": "留言已刪除", "description": "Moment" }, - "uJkv2X": { - "defaultMessage": "编辑标签" - }, "uM5qZr": { "defaultMessage": "我赞赏的" }, @@ -3336,9 +3213,6 @@ "defaultMessage": "支持了", "description": "src/components/Notice/TransactionNotice/PaymentReceivedDonationNotice.tsx" }, - "vLcHiG": { - "defaultMessage": "移除后,{user} 将无法继续参与「精选」作品管理。" - }, "vRCDr8": { "defaultMessage": "绑定后可以快速登入帐户{br}读者也能够透过其他管道自由转钱支持你!", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -3508,10 +3382,6 @@ "yOhatg": { "defaultMessage": "其他恶意行为" }, - "ySGgTo": { - "defaultMessage": "添加精选", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "ySSF/a": { "defaultMessage": "为了保障马特市市民的身份安全,我们升级了管理设定。请确认您的 Matters ID(确认后不可再次修改)", "description": "src/components/Dialogs/SetUserNameDialog/Content.tsx" @@ -3520,9 +3390,6 @@ "defaultMessage": "网络错误,请刷新页面", "description": "NETWORK_ERROR" }, - "yXWwSW": { - "defaultMessage": "确定要这么做吗 😭" - }, "yZfKI4": { "defaultMessage": " 眾聊提及你", "description": "src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index fbbffb8901..c5ad7aba33 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -127,15 +127,9 @@ "0/gRer": { "defaultMessage": "我正在搬家到 Matters,邀請你一起來" }, - "0/iEw/": { - "defaultMessage": "管理社群" - }, "06XHBC": { "defaultMessage": "加入圍爐" }, - "0Azlrb": { - "defaultMessage": "管理" - }, "0CyECR": { "defaultMessage": "Matters ID 已設置,更多帳號相關設置可前往設定頁修改", "description": "src/components/Dialogs/SetUserNameDialog/ConfirmStep.tsx" @@ -228,9 +222,6 @@ "defaultMessage": "尚無閱讀紀錄", "description": "src/views/Me/History/index.tsx" }, - "1ZFwRz": { - "defaultMessage": "確認移除" - }, "1exrSw": { "defaultMessage": "歡迎上船!" }, @@ -343,9 +334,6 @@ "3YAasP": { "defaultMessage": "什麼是 Liker ID?" }, - "3fqQHv": { - "defaultMessage": "添加協作者" - }, "3kbIhS": { "defaultMessage": "未命名" }, @@ -416,9 +404,6 @@ "defaultMessage": "確認要解綁 {type} 嗎?", "description": "src/components/Dialogs/RemoveSocialLoginDialog/Content.tsx" }, - "5FO4vn": { - "defaultMessage": "你尚無權限進行該操作" - }, "5Ga0iK": { "defaultMessage": "插入程式碼" }, @@ -480,10 +465,6 @@ "62nsdy": { "defaultMessage": "重試" }, - "63HuBz": { - "defaultMessage": "此標籤目前無人主理", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "69+D96": { "defaultMessage": "開始創作" }, @@ -609,10 +590,6 @@ "7oytv9": { "defaultMessage": "(修改過)" }, - "7xnrxG": { - "defaultMessage": "作品已添加至精選", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "7ykJ+l": { "defaultMessage": "暫無評論", "description": "src/components/Empty/EmptyComment.tsx" @@ -766,10 +743,6 @@ "AGDFGs": { "defaultMessage": "歧視、侮辱或仇恨" }, - "ANA7sk": { - "defaultMessage": "主理", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "AVpR3Q": { "defaultMessage": "已綁定錢包", "description": "src/components/UserProfile/WalletLabel/index.tsx" @@ -1102,10 +1075,6 @@ "GRrsEH": { "defaultMessage": "查看作品" }, - "GRtGnZ": { - "defaultMessage": "辭去權限", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "GU6vV0": { "defaultMessage": "尚未創建選集", "description": "src/components/Empty/EmptyCollection.tsx" @@ -1193,9 +1162,6 @@ "Hlwud7": { "defaultMessage": "更多 ENS 資訊請參考 {node}." }, - "Hm2DAQ": { - "defaultMessage": "確定移除協作者" - }, "HnxG15": { "defaultMessage": "設定" }, @@ -1301,10 +1267,6 @@ "Jr12wo": { "defaultMessage": "插入影片" }, - "Js/Fij": { - "defaultMessage": "作品已取消精選", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "Jxr/TM": { "defaultMessage": "已滿", "description": "src/components/Dialogs/AddCollectionsArticleDialog/SelectDialogContent.tsx" @@ -1330,10 +1292,6 @@ "defaultMessage": "圍爐創建成功", "description": "src/components/Forms/CreateCircleForm/Profile.tsx" }, - "KMcrz8": { - "defaultMessage": "認領", - "description": "src/views/TagDetail/Owner/index.tsx" - }, "KQi/UZ": { "defaultMessage": "封存作品" }, @@ -1348,9 +1306,6 @@ "defaultMessage": "錢包已綁定", "description": "src/components/Forms/WalletAuthForm/Connect.tsx" }, - "KoR0wt": { - "defaultMessage": "協作者可以與你共同管理精選" - }, "Kwv1n3": { "defaultMessage": " 用以出版 Writing NFT,費用 ≈1 LIKE,推廣期由平台補助" }, @@ -1377,10 +1332,6 @@ "defaultMessage": "展開", "description": "src/components/Expandable/index.tsx" }, - "L7Si5/": { - "defaultMessage": "管理社群", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "LETb4b": { "defaultMessage": "選集暫時不允許超過 {count} 篇", "description": "src/views/User/CollectionDetail/CollectionArticles/ViewerArticles.tsx" @@ -1423,9 +1374,6 @@ "defaultMessage": "你無法對此對象進行該操作", "description": "FORBIDDEN_BY_TARGET_STATE" }, - "LnesNr": { - "defaultMessage": "移除協作者成功" - }, "LoQ3BF": { "defaultMessage": "這枚徽章代表你完成了七天寫作,恭喜走完這趟意義非凡的寫作之旅!" }, @@ -1602,12 +1550,6 @@ "defaultMessage": "教學指南", "description": "src/components/Forms/PaymentForm/PayTo/SetAmount/SetAmountHeader/WhyOptimismDialog/index.tsx" }, - "P1AKC5": { - "defaultMessage": "協作者" - }, - "P2Btra": { - "defaultMessage": "認領成功" - }, "P3y9Bo": { "defaultMessage": "前往簽署", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -1693,9 +1635,6 @@ "QvPc1q": { "defaultMessage": "上傳封面" }, - "Qzdtxi": { - "defaultMessage": "辭去權限" - }, "R410ei": { "defaultMessage": "驗證碼錯誤", "description": "CODE_INVALID" @@ -1830,9 +1769,6 @@ "T9oZC8": { "defaultMessage": "確認要刪除該選集「{collection}」嗎?" }, - "TAPLOf": { - "defaultMessage": "每個標籤最多添加 {count} 名協作者" - }, "TF1OhT": { "defaultMessage": "臨時密碼已過期,請嘗試重新發送" }, @@ -1863,9 +1799,6 @@ "defaultMessage": "Optimism 是獨立運行的區塊鏈,若你在其他鏈上已有 USDT 貨幣,需要將它們轉移到 Optimism 網絡才能使用,詳情參考 {tutorial}.", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" }, - "ThSfXQ": { - "defaultMessage": "添加協作者成功" - }, "TjWWxF": { "defaultMessage": "廣播已送出", "description": "src/views/Circle/Broadcast/Broadcast.tsx" @@ -1910,10 +1843,6 @@ "defaultMessage": "移至底部", "description": "src/components/ArticleDigest/DropdownActions/SetBottomCollectionButton.tsx" }, - "UjKkhq": { - "defaultMessage": "作品已添加標籤", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "Up5U7K": { "defaultMessage": "封鎖" }, @@ -1924,9 +1853,6 @@ "Uq6tfM": { "defaultMessage": "添加說明文字…" }, - "Uv0hqn": { - "defaultMessage": "認領標籤" - }, "UxAA/V": { "defaultMessage": "Optimism 是基於以太坊的第二層(Layer2)擴容方案,能提升交易速度,並降低手續費,同時確保安全性,讓你更輕鬆地支持創作者。", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" @@ -2014,10 +1940,6 @@ "WQT8ZA": { "defaultMessage": "編輯選集" }, - "WSUAwk": { - "defaultMessage": "添加到精選", - "description": "src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx" - }, "WiGHyF": { "defaultMessage": "Web Monetization 標準" }, @@ -2217,9 +2139,6 @@ "defaultMessage": "讀者數量:訪問過作品頁的不重複的登入用戶數加匿名 IP 數(數據週期更新,可能存在延遲)", "description": "src/views/Me/Works/Published/SortTabs.tsx" }, - "a3j20X": { - "defaultMessage": "即刻主理" - }, "aCTmEO": { "defaultMessage": "我還沒有錢包", "description": "src/components/Forms/SelectAuthMethodForm/WalletFeed.tsx" @@ -2235,9 +2154,6 @@ "aKEiNd": { "defaultMessage": "錯過報名期沒關係,仍然可以用晚鳥身份參與,一起書寫人生故事。下次早點報名,就有機會獲得大滿貫徽章!" }, - "aKlTO2": { - "defaultMessage": "你還可以添加 {count} 名協作者" - }, "aOFCqL": { "defaultMessage": "最多評論", "description": "src/views/Me/Works/Published/SortTabs.tsx" @@ -2248,10 +2164,6 @@ "aTmmkr": { "defaultMessage": "你已經與圍爐告別,感謝曾經的付出與參與。" }, - "aa0nss": { - "defaultMessage": "取消精選", - "description": "src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx" - }, "aaUBvF": { "defaultMessage": " 中的發言", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" @@ -2409,9 +2321,6 @@ "deEeEI": { "defaultMessage": "註冊" }, - "dg3JCQ": { - "defaultMessage": "協作者" - }, "djJp6c": { "defaultMessage": "我的足跡" }, @@ -2438,9 +2347,6 @@ "eWXgsZ": { "defaultMessage": "清空内容" }, - "eXDZGQ": { - "defaultMessage": "主理人" - }, "eY3YIa": { "defaultMessage": "複製評論" }, @@ -2591,10 +2497,6 @@ "defaultMessage": "餘額不足:", "description": "src/components/Balance/index.tsx" }, - "hYG5fb": { - "defaultMessage": "人追蹤", - "description": "src/views/TagDetail/Followers/index.tsx" - }, "hgtWIO": { "defaultMessage": "作品被關聯", "description": "src/views/Me/Settings/Notifications/GeneralSettings/index.tsx" @@ -2696,9 +2598,6 @@ "defaultMessage": "在 {circlename} 發布廣播", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, - "k0ooDW": { - "defaultMessage": "標籤描述" - }, "k2veDA": { "defaultMessage": "創作" }, @@ -2715,9 +2614,6 @@ "kCPl0r": { "defaultMessage": "關聯" }, - "kCp8A9": { - "defaultMessage": "如果辭去權限,你將無法繼續管理標籤。" - }, "kEDrXh": { "defaultMessage": "喜歡你的選集" }, @@ -2796,9 +2692,6 @@ "lIir/P": { "defaultMessage": "我知道了" }, - "lMKb5N": { - "defaultMessage": "辭去權限成功" - }, "lNWFnL": { "defaultMessage": "分享這篇文章的翻譯版本" }, @@ -2809,9 +2702,6 @@ "lO7wKc": { "defaultMessage": "再想想" }, - "lT6Dt8": { - "defaultMessage": "確認辭去" - }, "lZukEr": { "defaultMessage": "評論了", "description": "src/components/Notice/CommentNotice/ArticleNewCommentNotice.tsx" @@ -2931,9 +2821,6 @@ "defaultMessage": "在", "description": "src/components/Notice/CommentCommentNotice/CommentNewReplyNotice.tsx" }, - "nNLkZ8": { - "defaultMessage": "新增協作者" - }, "nWhqw9": { "defaultMessage": "立即發布" }, @@ -3074,10 +2961,6 @@ "qhVSGI": { "defaultMessage": "吶,作者親手掩蓋了這篇作品的痕跡,看看別的吧" }, - "qlki7w": { - "defaultMessage": "移除作品", - "description": "src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx" - }, "qlxeW+": { "defaultMessage": "取消點踩" }, @@ -3120,9 +3003,6 @@ "defaultMessage": "開始修改", "description": "src/components/Dialogs/ReviseArticleDialog/index.tsx" }, - "rLlTQ9": { - "defaultMessage": "標籤名稱" - }, "rXnmeE": { "defaultMessage": "確認發送" }, @@ -3240,9 +3120,6 @@ "defaultMessage": "留言已刪除", "description": "Moment" }, - "uJkv2X": { - "defaultMessage": "編輯標籤" - }, "uM5qZr": { "defaultMessage": "我讚賞的" }, @@ -3336,9 +3213,6 @@ "defaultMessage": "支持了", "description": "src/components/Notice/TransactionNotice/PaymentReceivedDonationNotice.tsx" }, - "vLcHiG": { - "defaultMessage": "移除后,{user} 將無法繼續參與「精選」作品管理。" - }, "vRCDr8": { "defaultMessage": "綁定後可以快速登入帳戶{br}讀者也能夠透過其他管道自由轉錢支持你!", "description": "src/components/Forms/PaymentForm/BindWallet/index.tsx" @@ -3508,10 +3382,6 @@ "yOhatg": { "defaultMessage": "其他惡意行為" }, - "ySGgTo": { - "defaultMessage": "添加精選", - "description": "src/views/TagDetail/DropdownActions/index.tsx" - }, "ySSF/a": { "defaultMessage": "爲了保障馬特市市民的身份安全,我們升級了管理設定。請確認您的 Matters ID(確認後不可再次修改)", "description": "src/components/Dialogs/SetUserNameDialog/Content.tsx" @@ -3520,9 +3390,6 @@ "defaultMessage": "網路錯誤,請刷新頁面", "description": "NETWORK_ERROR" }, - "yXWwSW": { - "defaultMessage": "確定要這麼做嗎 😭" - }, "yZfKI4": { "defaultMessage": " 众聊提及你", "description": "src/components/Notice/CommentNotice/CommentMentionedYouNotice.tsx" diff --git a/src/common/enums/oauth.ts b/src/common/enums/oauth.ts index d310f3032b..5d9d60fc80 100644 --- a/src/common/enums/oauth.ts +++ b/src/common/enums/oauth.ts @@ -87,42 +87,18 @@ export const OAUTH_SCOPE_TREE = { zh_hant: '管理個人資料、標籤、評論、封鎖、追蹤等', zh_hans: '管理个人资料、标签、评论、封锁、关注等', }, - toggleSubscribeArticle: { + toggleBookmarkArticle: { _t: { zh_hant: '收藏作品', zh_hans: '收藏作品', }, }, - toggleFollowTag: { + toggleBookmarkTag: { _t: { zh_hant: '追蹤標籤', zh_hans: '关注标签', }, }, - updateTagSetting: { - _t: { - zh_hant: '管理標籤', - zh_hans: '管理标签', - }, - }, - addArticlesTags: { - _t: { - zh_hant: '添加作品到標籤', - zh_hans: '添加作品到标签', - }, - }, - updateArticlesTags: { - _t: { - zh_hant: '管理標籤作品', - zh_hans: '管理标签作品', - }, - }, - deleteArticlesTags: { - _t: { - zh_hant: '移除標籤作品', - zh_hans: '移除标签作品', - }, - }, togglePinComment: { _t: { zh_hant: '精选評論', diff --git a/src/components/ArticleDigest/DropdownActions/ArchiveArticle/Dialog.tsx b/src/components/ArticleDigest/DropdownActions/ArchiveArticle/Dialog.tsx index 416f15af9c..f8a06ee41f 100644 --- a/src/components/ArticleDigest/DropdownActions/ArchiveArticle/Dialog.tsx +++ b/src/components/ArticleDigest/DropdownActions/ArchiveArticle/Dialog.tsx @@ -22,7 +22,6 @@ const ARCHIVE_ARTICLE = gql` editArticle(input: { id: $id, state: archived }) { id articleState: state - sticky } } ` @@ -52,7 +51,6 @@ const ArchiveArticleDialog = ({ editArticle: { id: article.id, articleState: 'archived' as any, - sticky: false, __typename: 'Article', }, }, diff --git a/src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx b/src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx deleted file mode 100644 index 73becee7d3..0000000000 --- a/src/components/ArticleDigest/DropdownActions/RemoveTagButton.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import gql from 'graphql-tag' -import _isArray from 'lodash/isArray' -import { FormattedMessage } from 'react-intl' - -import { ReactComponent as IconCircleMinus } from '@/public/static/icons/24px/circle-minus.svg' -import { REFETCH_TAG_DETAIL_ARTICLES } from '~/common/enums' -import { Icon, Menu, useMutation } from '~/components' -import { updateTagArticlesCount } from '~/components/GQL' -import { - DeleteArticlesTagsMutation, - RemoveTagButtonArticleFragment, -} from '~/gql/graphql' - -const DELETE_ARTICLES_TAGS = gql` - mutation DeleteArticlesTags($id: ID!, $articles: [ID!]) { - deleteArticlesTags(input: { id: $id, articles: $articles }) { - id - articles(input: { first: 0, selected: true }) { - totalCount - } - } - } -` - -const fragments = { - article: gql` - fragment RemoveTagButtonArticle on Article { - id - tags { - id - creator { - id - } - editors { - id - } - } - } - `, -} - -const RemoveTagButton = ({ - article, - tagId, -}: { - article: RemoveTagButtonArticleFragment - tagId: string -}) => { - const [deleteArticlesTags] = useMutation( - DELETE_ARTICLES_TAGS, - { - variables: { id: tagId, articles: [article.id] }, - update: (cache) => { - updateTagArticlesCount({ cache, type: 'decrement', id: tagId }) - }, - } - ) - - return ( - - } - icon={} - onClick={async () => { - await deleteArticlesTags() - - window.dispatchEvent( - new CustomEvent(REFETCH_TAG_DETAIL_ARTICLES, { - detail: { - event: 'delete', - }, - }) - ) - }} - /> - ) -} - -RemoveTagButton.fragments = fragments - -export default RemoveTagButton diff --git a/src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx b/src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx deleted file mode 100644 index b049a29675..0000000000 --- a/src/components/ArticleDigest/DropdownActions/SetTagSelectedButton.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import gql from 'graphql-tag' -import { FormattedMessage } from 'react-intl' - -import { ReactComponent as IconCirclePlus } from '@/public/static/icons/24px/circle-plus.svg' -import { Icon, Menu, toast, useMutation } from '~/components' -import { - SetTagSelectedButtonArticleFragment, - SetTagSelectedMutation, -} from '~/gql/graphql' - -const SET_TAG_SELECTED = gql` - mutation SetTagSelected($id: ID!, $articles: [ID!]) { - updateArticlesTags( - input: { id: $id, articles: $articles, isSelected: true } - ) { - id - articles(input: { first: 0, selected: true }) { - totalCount - } - } - } -` - -const fragments = { - article: gql` - fragment SetTagSelectedButtonArticle on Article { - id - tags { - id - creator { - id - } - editors { - id - } - } - } - `, -} - -const SetTagSelectedButton = ({ - article, - tagId, -}: { - article: SetTagSelectedButtonArticleFragment - tagId: string -}) => { - const [update] = useMutation(SET_TAG_SELECTED, { - variables: { id: tagId, articles: [article.id] }, - }) - - return ( - - } - icon={} - onClick={async () => { - await update() - - toast.success({ - message: ( - - ), - }) - }} - /> - ) -} - -SetTagSelectedButton.fragments = fragments - -export default SetTagSelectedButton diff --git a/src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx b/src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx deleted file mode 100644 index 595b5e93fe..0000000000 --- a/src/components/ArticleDigest/DropdownActions/SetTagUnselectedButton.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import gql from 'graphql-tag' -import _filter from 'lodash/filter' -import _get from 'lodash/get' -import { FormattedMessage } from 'react-intl' - -import { ReactComponent as IconLTime } from '@/public/static/icons/24px/l-time.svg' -import { Icon, Menu, toast, useMutation } from '~/components' -import { - SetTagUnselectedButtonArticleFragment, - SetTagUnselectedMutation, - TagArticlesPublicQuery, -} from '~/gql/graphql' - -const SET_TAG_UNSELECTED = gql` - mutation SetTagUnselected($id: ID!, $articles: [ID!]) { - updateArticlesTags( - input: { id: $id, articles: $articles, isSelected: false } - ) { - id - articles(input: { first: 0, selected: true }) { - totalCount - } - } - } -` - -const fragments = { - article: gql` - fragment SetTagUnselectedButtonArticle on Article { - id - tags { - id - creator { - id - } - editors { - id - } - } - } - `, -} - -const SetTagUnselectedButton = ({ - article, - tagId, -}: { - article: SetTagUnselectedButtonArticleFragment - tagId: string -}) => { - const [update] = useMutation(SET_TAG_UNSELECTED, { - variables: { id: tagId, articles: [article.id] }, - update: (cache) => { - try { - // FIXME: circular dependencies - const { - TAG_ARTICLES_PUBLIC: query, - } = require('~/components/GQL/queries/tagArticles') - const variables = { - id: tagId, - selected: true, - sortBy: 'byCreatedAtDesc', - } - const data = cache.readQuery({ - query, - variables, - }) - const node = _get(data, 'node') - const articles = node?.__typename === 'Tag' ? node?.articles : null - - if (!articles || !articles?.edges || articles?.edges?.length === 0) { - return - } - - const newEdges = articles.edges.filter( - (item) => item.node.id !== article.id - ) - cache.writeQuery({ - query, - variables, - data: { - node: { - ...node, - articles: { - ...articles, - edges: newEdges, - }, - }, - }, - }) - sync() - } catch (error) { - console.error(error) - } - }, - }) - - const sync = () => { - toast.success({ - message: ( - - ), - }) - } - - return ( - - } - icon={} - onClick={async () => { - await update() - }} - /> - ) -} - -SetTagUnselectedButton.fragments = fragments - -export default SetTagUnselectedButton diff --git a/src/components/ArticleDigest/DropdownActions/gql.ts b/src/components/ArticleDigest/DropdownActions/gql.ts index cdc666d643..19c8d3f16d 100644 --- a/src/components/ArticleDigest/DropdownActions/gql.ts +++ b/src/components/ArticleDigest/DropdownActions/gql.ts @@ -10,9 +10,6 @@ import ArchiveArticle from './ArchiveArticle' import EditButton from './EditButton' import ExtendButton from './ExtendButton' import PinButton from './PinButton' -import RemoveTagButton from './RemoveTagButton' -import SetTagSelectedButton from './SetTagSelectedButton' -import SetTagUnselectedButton from './SetTagUnselectedButton' export const fragments = { article: gql` @@ -23,19 +20,13 @@ export const fragments = { ...ArchiveArticleArticle ...PinButtonArticle ...ExtendButtonArticle - ...RemoveTagButtonArticle ...EditArticleButtonArticle - ...SetTagSelectedButtonArticle - ...SetTagUnselectedButtonArticle } ${AppreciatorsDialog.fragments.article} ${SupportersDialog.fragments.article} ${PinButton.fragments.article} ${ArchiveArticle.fragments.article} ${ExtendButton.fragments.article} - ${RemoveTagButton.fragments.article} ${EditButton.fragments.article} - ${SetTagSelectedButton.fragments.article} - ${SetTagUnselectedButton.fragments.article} `, } diff --git a/src/components/ArticleDigest/DropdownActions/index.tsx b/src/components/ArticleDigest/DropdownActions/index.tsx index 2e086e3ca6..0e56fc90c2 100644 --- a/src/components/ArticleDigest/DropdownActions/index.tsx +++ b/src/components/ArticleDigest/DropdownActions/index.tsx @@ -49,10 +49,7 @@ import { fragments } from './gql' import IPFSButton from './IPFSButton' import PinButton from './PinButton' import RemoveArticleCollectionButton from './RemoveArticleCollectionButton' -import RemoveTagButton from './RemoveTagButton' import SetBottomCollectionButton from './SetBottomCollectionButton' -import SetTagSelectedButton from './SetTagSelectedButton' -import SetTagUnselectedButton from './SetTagUnselectedButton' import SetTopCollectionButton from './SetTopCollectionButton' import ShareButton from './ShareButton' import styles from './styles.module.css' @@ -278,16 +275,6 @@ const BaseDropdownActions = ({ )} - {hasSetTagSelected && tagDetailId && ( - - )} - {hasSetTagUnselected && tagDetailId && ( - - )} - {hasRemoveTag && tagDetailId && ( - - )} - {hasArchive && } {hasArchive && } diff --git a/src/components/ArticleDigest/Feed/index.tsx b/src/components/ArticleDigest/Feed/index.tsx index c0e8eec4d0..3fc6a22932 100644 --- a/src/components/ArticleDigest/Feed/index.tsx +++ b/src/components/ArticleDigest/Feed/index.tsx @@ -179,7 +179,7 @@ export const ArticleDigestFeed = React.memo( BaseArticleDigestFeed, ({ article: prevArticle, ...prevProps }, { article, ...props }) => { return ( - prevArticle.subscribed === article.subscribed && + prevArticle.bookmarked === article.bookmarked && prevArticle.articleState === article.articleState && prevArticle.pinned === article.pinned && prevProps.hasSetTagSelected === props.hasSetTagSelected && diff --git a/src/components/Buttons/Bookmark/Bookmark.test.tsx b/src/components/Buttons/Bookmark/Bookmark.test.tsx index 6933c2d0f4..cbf5878a3f 100644 --- a/src/components/Buttons/Bookmark/Bookmark.test.tsx +++ b/src/components/Buttons/Bookmark/Bookmark.test.tsx @@ -6,13 +6,13 @@ import { MOCK_ARTILCE } from '~/stories/mocks' describe('', () => { it('should render a bookmark button', () => { - render() + render() const $button = screen.getByRole('button', { name: 'Bookmark' }) expect($button).toBeInTheDocument() }) it('should render a remove bookmark button', () => { - render() + render() const $button = screen.getByRole('button', { name: 'Remove bookmark' }) expect($button).toBeInTheDocument() }) diff --git a/src/components/Buttons/Bookmark/Subscribe.tsx b/src/components/Buttons/Bookmark/Subscribe.tsx index b070ee00f7..c50b67f6de 100644 --- a/src/components/Buttons/Bookmark/Subscribe.tsx +++ b/src/components/Buttons/Bookmark/Subscribe.tsx @@ -19,9 +19,9 @@ import { useMutation, ViewerContext, } from '~/components' -import { ToggleSubscribeArticleMutation } from '~/gql/graphql' +import { ToggleBookmarkArticleMutation } from '~/gql/graphql' -import TOGGLE_SUBSCRIBE_ARTICLE from '../../GQL/mutations/toggleSubscribeArticle' +import TOGGLE_BOOKMARK_ARTICLE from '../../GQL/mutations/toggleBookmarkArticle' export type SubscribeProps = { articleId?: string @@ -40,8 +40,8 @@ const Subscribe = ({ const viewer = useContext(ViewerContext) const intl = useIntl() - const [subscribe] = useMutation( - TOGGLE_SUBSCRIBE_ARTICLE, + const [subscribe] = useMutation( + TOGGLE_BOOKMARK_ARTICLE, { variables: { id: articleId, enabled: true }, } diff --git a/src/components/Buttons/Bookmark/Unsubscribe.tsx b/src/components/Buttons/Bookmark/Unsubscribe.tsx index 475522531a..46ad5bd880 100644 --- a/src/components/Buttons/Bookmark/Unsubscribe.tsx +++ b/src/components/Buttons/Bookmark/Unsubscribe.tsx @@ -13,9 +13,9 @@ import { useMutation, ViewerContext, } from '~/components' -import { ToggleSubscribeArticleMutation } from '~/gql/graphql' +import { ToggleBookmarkArticleMutation } from '~/gql/graphql' -import TOGGLE_SUBSCRIBE_ARTICLE from '../../GQL/mutations/toggleSubscribeArticle' +import TOGGLE_BOOKMARK_ARTICLE from '../../GQL/mutations/toggleBookmarkArticle' export type UnsubscribeProps = { articleId?: string @@ -34,8 +34,8 @@ const Unsubscribe = ({ const viewer = useContext(ViewerContext) const intl = useIntl() - const [unsubscribe] = useMutation( - TOGGLE_SUBSCRIBE_ARTICLE, + const [unsubscribe] = useMutation( + TOGGLE_BOOKMARK_ARTICLE, { variables: { id: articleId, enabled: false }, } diff --git a/src/components/Buttons/Bookmark/index.tsx b/src/components/Buttons/Bookmark/index.tsx index b8b1029f31..6409e0eaf5 100644 --- a/src/components/Buttons/Bookmark/index.tsx +++ b/src/components/Buttons/Bookmark/index.tsx @@ -18,7 +18,7 @@ const fragments = { private: gql` fragment BookmarkArticlePrivate on Article { id - subscribed + bookmarked } `, }, @@ -32,7 +32,7 @@ export const BookmarkButton = ({ }: BookmarkButtonProps) => { const viewer = useContext(ViewerContext) - if (article.subscribed) { + if (article.bookmarked) { return ( void -} & EditTagDialogContentProps - -interface FormValues { - newContent: string - newCover?: string - newDescription: string -} - -const UNCHANGED_FIELD = 'UNCHANGED_FIELD' - -const EditTagDialogContent: React.FC = ({ - id, - content, - cover, - description, - closeDialog, -}) => { - const intl = useIntl() - const [update] = useMutation(PUT_TAG, undefined, { - showToast: false, - }) - const formId = 'put-tag-form' - - const { - values, - errors, - touched, - handleBlur, - handleChange, - handleSubmit, - isSubmitting, - setFieldValue, - } = useFormik({ - initialValues: { - newContent: content || '', - newCover: UNCHANGED_FIELD, - newDescription: description || '', - }, - validateOnBlur: false, - validateOnChange: false, - validate: ({ newContent }) => - _pickBy({ - newContent: validateTagName(newContent, intl), - }), - - onSubmit: async ( - { newContent, newCover, newDescription }, - { setFieldError, setSubmitting } - ) => { - try { - await update({ - variables: { - input: { - id, - content: newContent, - description: newDescription, - ...(newCover !== UNCHANGED_FIELD ? { cover: newCover } : {}), - }, - }, - }) - - toast.success({ - message: , - }) - - setSubmitting(false) - - closeDialog() - } catch (error) { - setSubmitting(false) - - const [messages, codes] = parseFormSubmitErrors(error as any) - setFieldError('newContent', intl.formatMessage(messages[codes[0]])) - } - }, - }) - - const [coverLoading, setCoverLoading] = useState(false) - const InnerForm = ( -
    -
    - setFieldValue('newCover', assetId)} - onUploadStart={() => setCoverLoading(true)} - onUploadEnd={() => setCoverLoading(false)} - onReset={() => setFieldValue('newCover', null)} - /> -
    - - { - const newContent = normalizeTag(e.target.value) - setFieldValue('newContent', newContent) - return newContent - }} - maxLength={MAX_TAG_CONTENT_LENGTH} - hint={`${values.newContent.length}/${MAX_TAG_CONTENT_LENGTH}`} - error={touched.newContent && errors.newContent} - hintAlign={touched.newContent && errors.newContent ? 'left' : 'right'} - spacingTop="loose" - spacingBottom="base" - /> - - - - ) - - const SubmitButton = ( - } - type="submit" - form={formId} - disabled={isSubmitting || coverLoading} - loading={isSubmitting || coverLoading} - /> - ) - - return ( - <> - } - closeDialog={closeDialog} - rightBtn={SubmitButton} - hasSmUpTitle={false} - /> - - {InnerForm} - - - } - color="greyDarker" - onClick={closeDialog} - /> - {SubmitButton} - - } - /> - - ) -} - -export default EditTagDialogContent diff --git a/src/components/Dialogs/EditTagDialog/index.tsx b/src/components/Dialogs/EditTagDialog/index.tsx deleted file mode 100644 index 3b4cd59aa1..0000000000 --- a/src/components/Dialogs/EditTagDialog/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import dynamic from 'next/dynamic' - -import { Dialog, SpinnerBlock, useDialogSwitch } from '~/components' - -import { EditTagDialogContentProps } from './Content' - -export type EditTagDialogProps = EditTagDialogContentProps - -const DynamicContent = dynamic(() => import('./Content'), { - ssr: false, - loading: () => , -}) - -type BaseEditTagDialogProps = { - children: ({ openDialog }: { openDialog: () => void }) => React.ReactNode -} & EditTagDialogProps - -const BaseEditTagDialog = ({ - children, - content, - ...restProps -}: BaseEditTagDialogProps) => { - const { show, openDialog, closeDialog } = useDialogSwitch(true) - - return ( - <> - {children({ openDialog })} - - - - - - ) -} - -export const EditTagDialog = (props: BaseEditTagDialogProps) => ( - }> - {({ openDialog }) => <>{props.children({ openDialog })}} - -) diff --git a/src/components/Dialogs/EditTagDialog/styles.module.css b/src/components/Dialogs/EditTagDialog/styles.module.css deleted file mode 100644 index dfb72e5055..0000000000 --- a/src/components/Dialogs/EditTagDialog/styles.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.coverField { - margin: calc(var(--sp16) * -1) calc(var(--sp16) * -1) 0; - - @media (--sm-up) { - margin: 0 calc(var(--sp20) * -1); - } -} diff --git a/src/components/Dialogs/TagAdoptionDialog/index.tsx b/src/components/Dialogs/TagAdoptionDialog/index.tsx deleted file mode 100644 index dc08570408..0000000000 --- a/src/components/Dialogs/TagAdoptionDialog/index.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { useContext } from 'react' -import { FormattedMessage } from 'react-intl' - -import { - Dialog, - LanguageContext, - toast, - useDialogSwitch, - useMutation, -} from '~/components' -import UPDATE_TAG_SETTING from '~/components/GQL/mutations/updateTagSetting' -import { UpdateTagSettingMutation } from '~/gql/graphql' - -interface Props { - id: string - children: ({ openDialog }: { openDialog: () => void }) => React.ReactNode -} - -const texts = { - zh_hans: - '当你认领标签后,即刻成为该标签的主理人。' + - '你将可以为标签设置封面,编辑描述,并添加作品至精选列表。' + - '你主理的标签可以用作文集、策展,也可以变成圈子、小组、讨论区等,更多主理人玩法等你发掘!', - zh_hant: - '當你認領標籤後,即刻成為該標籤的主理人。' + - '你將可以為標籤設置封面,編輯描述,並添加作品至精選列表。' + - '你主理的標籤可以用作文集、策展,也可以變成圈子、小組、討論區等,更多主理人玩法等你發掘!', - en: - 'After adopting the tag, you become the maintainer of it.' + - ' You can set the cover and description of the tag, and add works to selected feed. ' + - ' You can use it for writing collection, curation, or subcommunity and group discussions, be creative and discover new usages!', -} - -const BaseDialog = ({ id, children }: Props) => { - const { lang } = useContext(LanguageContext) - const { show, openDialog, closeDialog } = useDialogSwitch(true) - - const [update, { loading }] = - useMutation(UPDATE_TAG_SETTING) - - const onClick = async () => { - const result = await update({ - variables: { input: { id, type: 'adopt' } }, - }) - - if (!result) { - throw new Error('tag adoption failed') - } - - toast.success({ - message: , - }) - } - - return ( - <> - {children({ openDialog })} - - - } - /> - - - -

    {texts[lang]}

    -
    -
    - - - } - btns={ - - } - loading={loading} - onClick={onClick} - /> - } - smUpBtns={ - - } - loading={loading} - onClick={onClick} - /> - } - /> -
    - - ) -} - -export const TagAdoptionDialog = (props: Props) => ( - }> - {({ openDialog }) => <>{props.children({ openDialog })}} - -) diff --git a/src/components/Dialogs/TagEditorDialog/List/index.tsx b/src/components/Dialogs/TagEditorDialog/List/index.tsx deleted file mode 100644 index 1aeef23f33..0000000000 --- a/src/components/Dialogs/TagEditorDialog/List/index.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import { useQuery } from '@apollo/react-hooks' -import { FormattedMessage } from 'react-intl' - -import { - Button, - Dialog, - List, - QueryError, - Spacer, - SpinnerBlock, - TextIcon, - UserDigest, -} from '~/components' -import TAG_MAINTAINERS from '~/components/GQL/queries/tagMaintainers' -import { TagMaintainersQuery } from '~/gql/graphql' - -import styles from './styles.module.css' - -/** - * This a sub-component of . It shows editors of a tag, and - * user can start to add or remove editors in this. - * - * Usage: - * - * ```tsx - * {}} - * toAddStep={() => {}} - * toRemoveStep={() => {}} - * /> - * ``` - */ -type TagMaintainersNodeTagEditor = NonNullable< - NonNullable['editors'] ->[0] - -interface Props { - id: string - - closeDialog: () => void - toAddStep: () => void - toRemoveStep: (editor: TagMaintainersNodeTagEditor) => void -} - -const RemoveButton = ({ remove }: { remove: () => void }) => ( -
    - -
    -) - -const TagEditorList = ({ id, closeDialog, toAddStep, toRemoveStep }: Props) => { - const { data, loading, error } = useQuery( - TAG_MAINTAINERS, - { - variables: { id }, - } - ) - - if (loading) { - return - } - - if (error) { - return - } - - const tag = data?.node?.__typename === 'Tag' && data?.node - - if (!tag) { - return null - } - - const editors = tag.editors || [] - const count = editors.length - - const isAllowAdd = count < 4 - const isHavingEditors = count > 0 - const isHavingNoneEditors = count === 0 - const isReachingLimit = count === 4 - - const AddEditorButton = () => ( - } - onClick={toAddStep} - /> - ) - - return ( - <> - - } - closeDialog={closeDialog} - rightBtn={} - /> - - - - {tag.owner && ( - - - } - spacing={[12, 16]} - hasFollow={false} - /> - - )} - - {editors.map((editor) => ( - - - } - extraButton={ - toRemoveStep(editor)} /> - } - spacing={[12, 16]} - /> - - ))} - - - - - - -

    - - - {(isHavingNoneEditors || isReachingLimit) && ( -

    - 4 , - }} - /> -

    - )} - - {isAllowAdd && isHavingEditors && ( -

    - {4 - count} - ), - }} - /> -

    - )} -

    -
    -
    - - -
    - - {isAllowAdd && ( - - } - color="greyDarker" - onClick={closeDialog} - /> - - - } - /> - )} - - ) -} - -export default TagEditorList diff --git a/src/components/Dialogs/TagEditorDialog/List/styles.module.css b/src/components/Dialogs/TagEditorDialog/List/styles.module.css deleted file mode 100644 index 2ff7f7c835..0000000000 --- a/src/components/Dialogs/TagEditorDialog/List/styles.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.count { - color: var(--color-matters-green); -} diff --git a/src/components/Dialogs/TagEditorDialog/Remove/index.tsx b/src/components/Dialogs/TagEditorDialog/Remove/index.tsx deleted file mode 100644 index 92c22df087..0000000000 --- a/src/components/Dialogs/TagEditorDialog/Remove/index.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { FormattedMessage } from 'react-intl' - -import { Dialog, toast, Translate, useMutation } from '~/components' -import { updateTagMaintainers } from '~/components/GQL' -import UPDATE_TAG_SETTING from '~/components/GQL/mutations/updateTagSetting' -import { TagMaintainersQuery, UpdateTagSettingMutation } from '~/gql/graphql' - -import styles from './styles.module.css' - -/** - * This a sub-component of . It ask user to confirm - * of removal of selected editor. - * - * Usage: - * - * ```tsx - * {}} - * /> - * ``` - */ - -type TagMaintainersNodeTagEditor = NonNullable< - NonNullable['editors'] ->[0] - -interface Props { - id: string - editor: TagMaintainersNodeTagEditor - - closeDialog: () => void -} - -const TagRemoveEditor = ({ id, editor, closeDialog }: Props) => { - const [update, { loading }] = - useMutation(UPDATE_TAG_SETTING) - - const onClick = async () => { - const result = await update({ - variables: { - input: { id, type: 'remove_editor', editors: [editor.id] }, - }, - update: (cache) => - updateTagMaintainers({ - cache, - id, - type: 'remove', - editors: [editor.id], - }), - }) - - if (!result) { - throw new Error('tag leave failed') - } - - toast.success({ - message: ( - - ), - }) - - closeDialog() - } - - return ( - <> - - } - /> - - - -

    - {editor.displayName}, - }} - /> - -

    -
    -
    - - - } - color={loading ? 'green' : 'red'} - onClick={onClick} - loading={loading} - /> - } - smUpBtns={ - - } - color={loading ? 'green' : 'red'} - onClick={onClick} - loading={loading} - /> - } - /> - - ) -} - -export default TagRemoveEditor diff --git a/src/components/Dialogs/TagEditorDialog/Remove/styles.module.css b/src/components/Dialogs/TagEditorDialog/Remove/styles.module.css deleted file mode 100644 index 275c1b0094..0000000000 --- a/src/components/Dialogs/TagEditorDialog/Remove/styles.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.name { - font-weight: var(--font-medium); - color: var(--color-black); -} diff --git a/src/components/Dialogs/TagEditorDialog/SearchSelect/index.tsx b/src/components/Dialogs/TagEditorDialog/SearchSelect/index.tsx deleted file mode 100644 index 28356301aa..0000000000 --- a/src/components/Dialogs/TagEditorDialog/SearchSelect/index.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import _get from 'lodash/get' -import { useState } from 'react' -import { FormattedMessage } from 'react-intl' - -import { Dialog, toast, useMutation } from '~/components' -import { updateTagMaintainers } from '~/components/GQL' -import UPDATE_TAG_SETTING from '~/components/GQL/mutations/updateTagSetting' -import SearchingArea, { - SelectNode, -} from '~/components/SearchSelect/SearchingArea' -import StagingArea, { StagingNode } from '~/components/SearchSelect/StagingArea' -import { UpdateTagSettingMutation } from '~/gql/graphql' - -interface Props { - id: string - - closeDialog: () => void - toListStep: () => void -} - -type Area = 'staging' | 'searching' - -/** - * This is a sub-component of . It allows user to search and - * select nodes from search results, and then submit selected nodes. - * - * Usage: - * - * ```tsx - * {}} - * /> - * ``` - */ -const TagSearchSelectEditor = ({ id, closeDialog, toListStep }: Props) => { - const [update, { loading }] = - useMutation(UPDATE_TAG_SETTING) - - // area - const [area, setArea] = useState('staging') - const inStagingArea = area === 'staging' - const inSearchingArea = area === 'searching' - const toStagingArea = () => setArea('staging') - const toSearchingArea = () => setArea('searching') - - // data - const [stagingNodes, setStagingNodes] = useState([]) - const addNodeToStaging = (node: SelectNode) => { - const isExists = stagingNodes.some(({ node: n }) => n.id === node.id) - - if (!isExists) { - setStagingNodes([...stagingNodes, { node, selected: true }]) - } - - toStagingArea() - } - - const onClickSave = async () => { - const editors = stagingNodes.filter(({ selected }) => !!selected) - const result = await update({ - variables: { - input: { - id, - type: 'add_editor', - editors: editors.map(({ node }) => node.id), - }, - }, - update: (cache) => { - // filter out matty for local cache update - const filteredEditors = editors.filter( - ({ node }) => _get(node, 'displayName') !== 'Matty' - ) - updateTagMaintainers({ - cache, - id, - type: 'add', - editors: filteredEditors, - }) - }, - }) - - if (!result) { - return - } - - toast.success({ - message: ( - - ), - }) - - closeDialog() - } - - const SubmitButton = ( - } - loading={loading} - /> - ) - - return ( - <> - } - closeDialog={closeDialog} - rightBtn={SubmitButton} - /> - - - - - } - inStagingArea={inStagingArea} - draggable={false} - /> - - - - } - color="greyDarker" - onClick={closeDialog} - /> - {SubmitButton} - - } - /> - - ) -} - -export default TagSearchSelectEditor diff --git a/src/components/Dialogs/TagEditorDialog/index.tsx b/src/components/Dialogs/TagEditorDialog/index.tsx deleted file mode 100644 index 3bf2397047..0000000000 --- a/src/components/Dialogs/TagEditorDialog/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { useState } from 'react' - -import { - Dialog, - useDialogSwitch, // useRoute, - useStep, -} from '~/components' -import { TagMaintainersQuery } from '~/gql/graphql' - -import TagEditorList from './List' -import TagRemoveEditor from './Remove' -import TagSearchSelectEditor from './SearchSelect' - -/** - * TagEditorDialog is composed of three steps: list, add and remove. - * - * Usage: - * - * ```tsx - * - * {({ openDialog })=> ()} - * - * ``` - */ -type Step = 'list' | 'add' | 'remove' - -type TagMaintainersNodeTagEditor = NonNullable< - NonNullable['editors'] ->[0] - -export interface TagEditorDialogProps { - id: string - children: ({ openDialog }: { openDialog: () => void }) => React.ReactNode -} - -const BaseDialog = ({ id, children }: TagEditorDialogProps) => { - const defaultStep = 'list' - - const { - show, - openDialog: baseOpenDialog, - closeDialog, - } = useDialogSwitch(true) - const [removeEditor, setRemoveEditor] = - useState() - const { currStep, forward, reset } = useStep(defaultStep) - - const openDialog = () => { - if (currStep !== defaultStep) { - reset(defaultStep) - } - setRemoveEditor(undefined) - baseOpenDialog() - } - - const isAdd = currStep === 'add' - const isList = currStep === 'list' - const isRemove = currStep === 'remove' - - return ( - <> - {children({ openDialog })} - - - {isList && ( - forward('add')} - toRemoveStep={(editor: TagMaintainersNodeTagEditor) => { - setRemoveEditor(editor) - forward('remove') - }} - /> - )} - - {isAdd && ( - forward('list')} - /> - )} - - {isRemove && removeEditor && ( - - )} - - - ) -} - -export const TagEditorDialog = (props: TagEditorDialogProps) => ( - }> - {({ openDialog }) => <>{props.children({ openDialog })}} - -) diff --git a/src/components/Dialogs/TagLeaveDialog/index.tsx b/src/components/Dialogs/TagLeaveDialog/index.tsx deleted file mode 100644 index e6ade8dde0..0000000000 --- a/src/components/Dialogs/TagLeaveDialog/index.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { FormattedMessage } from 'react-intl' - -import { Dialog, toast, useDialogSwitch, useMutation } from '~/components' -import UPDATE_TAG_SETTING from '~/components/GQL/mutations/updateTagSetting' -import { UpdateTagSettingMutation } from '~/gql/graphql' - -export interface TagLeaveDialogProps { - id: string - isOwner?: boolean - children: ({ openDialog }: { openDialog: () => void }) => React.ReactNode -} - -const BaseDialog = ({ id, isOwner, children }: TagLeaveDialogProps) => { - const { show, openDialog, closeDialog } = useDialogSwitch(true) - - const [update, { loading }] = - useMutation(UPDATE_TAG_SETTING) - - const onClick = async () => { - const result = await update({ - variables: { - input: { id, type: isOwner ? 'leave' : 'leave_editor' }, - }, - }) - - if (!result) { - throw new Error('tag leave failed') - } - - toast.success({ - message: ( - - ), - }) - - closeDialog() - } - - return ( - <> - {children({ openDialog })} - - - - } - /> - - - -

    - -

    -

    - -

    -
    -
    - - - } - color={loading ? 'green' : 'red'} - onClick={onClick} - loading={loading} - /> - } - smUpBtns={ - - } - color={loading ? 'green' : 'red'} - onClick={onClick} - loading={loading} - /> - } - /> -
    - - ) -} - -export const TagLeaveDialog = (props: TagLeaveDialogProps) => ( - }> - {({ openDialog }) => <>{props.children({ openDialog })}} - -) diff --git a/src/components/Dialogs/index.tsx b/src/components/Dialogs/index.tsx index 5884df31ad..629e2215c0 100644 --- a/src/components/Dialogs/index.tsx +++ b/src/components/Dialogs/index.tsx @@ -37,12 +37,6 @@ export * from './RemoveArticleCollectionDialog' // Editor export * from './EditorSearchSelectDialog' -// Tag -export * from './EditTagDialog' -export * from './TagAdoptionDialog' -export * from './TagEditorDialog' -export * from './TagLeaveDialog' - // Re-use export * from './SearchSelectDialog' diff --git a/src/components/GQL/fragments/tag.ts b/src/components/GQL/fragments/tag.ts index 9134e91560..c01009e6f4 100644 --- a/src/components/GQL/fragments/tag.ts +++ b/src/components/GQL/fragments/tag.ts @@ -1,32 +1,12 @@ import gql from 'graphql-tag' -import { Avatar } from '~/components/Avatar' - const fragments = { - followers: gql` - fragment FollowersTag on Tag { - id - followers(input: { first: 5 }) { - totalCount - edges { - cursor - node { - ... on User { - id - ...AvatarUser - } - } - } - } - } - ${Avatar.fragments.user} - `, articleCount: gql` fragment ArticleCountTag on Tag { id numAuthors numArticles - articles(input: { first: 0, selected: false }) { + articles(input: { first: 0 }) { totalCount } } diff --git a/src/components/GQL/mutations/addArticlesTags.ts b/src/components/GQL/mutations/addArticlesTags.ts deleted file mode 100644 index cc7df5376b..0000000000 --- a/src/components/GQL/mutations/addArticlesTags.ts +++ /dev/null @@ -1,14 +0,0 @@ -import gql from 'graphql-tag' - -export default gql` - mutation AddArticlesTags($id: ID!, $articles: [ID!], $selected: Boolean) { - addArticlesTags( - input: { id: $id, articles: $articles, selected: $selected } - ) { - id - articles(input: { first: 0, selected: $selected }) { - totalCount - } - } - } -` diff --git a/src/components/GQL/mutations/changeEmail.ts b/src/components/GQL/mutations/changeEmail.ts deleted file mode 100644 index 778f403a7d..0000000000 --- a/src/components/GQL/mutations/changeEmail.ts +++ /dev/null @@ -1,12 +0,0 @@ -import gql from 'graphql-tag' - -export const CHANGE_EMAIL = gql` - mutation ChangeEmail($input: ChangeEmailInput!) { - changeEmail(input: $input) { - id - info { - email - } - } - } -` diff --git a/src/components/GQL/mutations/toggleBookmarkArticle.ts b/src/components/GQL/mutations/toggleBookmarkArticle.ts new file mode 100644 index 0000000000..dc98afe05a --- /dev/null +++ b/src/components/GQL/mutations/toggleBookmarkArticle.ts @@ -0,0 +1,10 @@ +import gql from 'graphql-tag' + +export default gql` + mutation ToggleBookmarkArticle($id: ID!, $enabled: Boolean) { + toggleBookmarkArticle(input: { id: $id, enabled: $enabled }) { + id + bookmarked + } + } +` diff --git a/src/components/GQL/mutations/toggleBookmarkTag.ts b/src/components/GQL/mutations/toggleBookmarkTag.ts new file mode 100644 index 0000000000..27f66a3a99 --- /dev/null +++ b/src/components/GQL/mutations/toggleBookmarkTag.ts @@ -0,0 +1,10 @@ +import gql from 'graphql-tag' + +export default gql` + mutation ToggleBookmarkTag($id: ID!, $enabled: Boolean) { + toggleBookmarkTag(input: { id: $id, enabled: $enabled }) { + id + isFollower + } + } +` diff --git a/src/components/GQL/mutations/toggleFollowTag.ts b/src/components/GQL/mutations/toggleFollowTag.ts deleted file mode 100644 index 9cf4224cae..0000000000 --- a/src/components/GQL/mutations/toggleFollowTag.ts +++ /dev/null @@ -1,10 +0,0 @@ -import gql from 'graphql-tag' - -export default gql` - mutation ToggleFollowTag($id: ID!, $enabled: Boolean) { - toggleFollowTag(input: { id: $id, enabled: $enabled }) { - id - isFollower - } - } -` diff --git a/src/components/GQL/mutations/toggleSubscribeArticle.ts b/src/components/GQL/mutations/toggleSubscribeArticle.ts deleted file mode 100644 index 9f0948275d..0000000000 --- a/src/components/GQL/mutations/toggleSubscribeArticle.ts +++ /dev/null @@ -1,10 +0,0 @@ -import gql from 'graphql-tag' - -export default gql` - mutation ToggleSubscribeArticle($id: ID!, $enabled: Boolean) { - toggleSubscribeArticle(input: { id: $id, enabled: $enabled }) { - id - subscribed - } - } -` diff --git a/src/components/GQL/mutations/updateTagSetting.ts b/src/components/GQL/mutations/updateTagSetting.ts deleted file mode 100644 index d26db45c0e..0000000000 --- a/src/components/GQL/mutations/updateTagSetting.ts +++ /dev/null @@ -1,29 +0,0 @@ -import gql from 'graphql-tag' - -import { Avatar } from '~/components/Avatar' - -import Tag from '../fragments/tag' - -export default gql` - mutation UpdateTagSetting($input: UpdateTagSettingInput!) { - updateTagSetting(input: $input) { - id - editors { - id - ...AvatarUser - } - owner { - id - userName - displayName - status { - state - } - ...AvatarUser - } - ...FollowersTag - } - } - ${Avatar.fragments.user} - ${Tag.followers} -` diff --git a/src/components/GQL/queries/tagArticles.ts b/src/components/GQL/queries/tagArticles.ts index baf1ff6125..c0a0f0fac6 100644 --- a/src/components/GQL/queries/tagArticles.ts +++ b/src/components/GQL/queries/tagArticles.ts @@ -6,20 +6,12 @@ export const TAG_ARTICLES_PUBLIC = gql` query TagArticlesPublic( $id: ID! $after: String - $selected: Boolean $sortBy: TagArticlesSortBy ) { node(input: { id: $id }) { ... on Tag { id - articles( - input: { - first: 20 - after: $after - selected: $selected - sortBy: $sortBy - } - ) { + articles(input: { first: 20, after: $after, sortBy: $sortBy }) { pageInfo { startCursor endCursor diff --git a/src/components/GQL/queries/tagFollowers.ts b/src/components/GQL/queries/tagFollowers.ts deleted file mode 100644 index e1c384d248..0000000000 --- a/src/components/GQL/queries/tagFollowers.ts +++ /dev/null @@ -1,15 +0,0 @@ -import gql from 'graphql-tag' - -import tagFragments from '../fragments/tag' - -export default gql` - query TagFollowers($id: ID!) { - node(input: { id: $id }) { - ... on Tag { - id - ...FollowersTag - } - } - } - ${tagFragments.followers} -` diff --git a/src/components/GQL/queries/tagMaintainers.ts b/src/components/GQL/queries/tagMaintainers.ts deleted file mode 100644 index fe3c872020..0000000000 --- a/src/components/GQL/queries/tagMaintainers.ts +++ /dev/null @@ -1,23 +0,0 @@ -import gql from 'graphql-tag' - -import { UserDigest } from '~/components/UserDigest' - -export default gql` - query TagMaintainers($id: ID!) { - node(input: { id: $id }) { - ... on Tag { - id - owner { - id - ...UserDigestRichUserPublic - } - editors(input: { excludeAdmin: true, excludeOwner: true }) { - id - ...UserDigestRichUserPublic - } - __typename - } - } - } - ${UserDigest.Rich.fragments.user.public} -` diff --git a/src/components/GQL/queries/walletBalance.ts b/src/components/GQL/queries/walletBalance.ts index 292f0edad4..27f7827bc5 100644 --- a/src/components/GQL/queries/walletBalance.ts +++ b/src/components/GQL/queries/walletBalance.ts @@ -14,7 +14,6 @@ export default gql` } liker { total - rateUSD } } } diff --git a/src/components/GQL/updates/index.ts b/src/components/GQL/updates/index.ts index d3cd122567..5c66de9d90 100644 --- a/src/components/GQL/updates/index.ts +++ b/src/components/GQL/updates/index.ts @@ -7,8 +7,6 @@ export * from './commentDetail' export * from './draftAssets' export * from './momentDetail' export * from './tagArticlesCount' -export * from './tagFollowers' -export * from './tagMaintainers' export * from './userCollectionDetail' export * from './userCollections' export * from './userCollectionsArticles' diff --git a/src/components/GQL/updates/tagFollowers.ts b/src/components/GQL/updates/tagFollowers.ts deleted file mode 100644 index 94bfb93025..0000000000 --- a/src/components/GQL/updates/tagFollowers.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { DataProxy } from 'apollo-cache' - -import TAG_FOLLOWERS from '~/components/GQL/queries/tagFollowers' -import { TagFollowersQuery } from '~/gql/graphql' - -export const updateTagFollowers = ({ - cache, - id, - type, - viewer, -}: { - cache: DataProxy - id: string - type: 'follow' | 'unfollow' - viewer: any -}) => { - try { - if (!id) { - return - } - - const variables = { id } - const cacheData = cache.readQuery({ - query: TAG_FOLLOWERS, - variables, - }) - - if (!cacheData || !cacheData.node || cacheData.node.__typename !== 'Tag') { - return - } - - const followers = cacheData.node.followers.edges || [] - if (type === 'follow') { - followers.unshift({ - cursor: window.btoa(`arrayconnection:${followers.length}:0`) || '', - node: { - avatar: viewer.avatar, - id: viewer.id, - liker: { - civicLiker: viewer.liker.civicLiker, - __typename: 'Liker', - }, - info: { - badges: viewer.info.badges, - __typename: 'UserInfo', - }, - __typename: 'User', - }, - __typename: 'UserEdge', - }) - cacheData.node.followers.edges = followers - cacheData.node.followers.totalCount++ - } else { - cacheData.node.followers.edges = followers.filter( - (follower) => follower.node.id !== viewer.id - ) - cacheData.node.followers.totalCount-- - } - - cache.writeQuery({ - query: TAG_FOLLOWERS, - variables, - data: cacheData, - }) - } catch (e) { - console.error(e) - } -} diff --git a/src/components/GQL/updates/tagMaintainers.ts b/src/components/GQL/updates/tagMaintainers.ts deleted file mode 100644 index e388690d52..0000000000 --- a/src/components/GQL/updates/tagMaintainers.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { DataProxy } from 'apollo-cache' -import _omit from 'lodash/omit' - -import TAG_MAINTAINERS from '~/components/GQL/queries/tagMaintainers' -import { TagMaintainersQuery } from '~/gql/graphql' - -type TagMaintainersNodeTagEditor = NonNullable< - NonNullable['editors'] ->[0] - -export const updateTagMaintainers = ({ - cache, - id, - type, - editors, -}: { - cache: DataProxy - id: string - type: 'add' | 'remove' - editors: any[] -}) => { - try { - if (!id) { - return - } - - const variables = { id } - const cacheData = cache.readQuery({ - query: TAG_MAINTAINERS, - variables, - }) - - if (!cacheData || !cacheData.node || cacheData.node.__typename !== 'Tag') { - return - } - - const currEditors = cacheData.node.editors || [] - - switch (type) { - case 'add': { - const newEditors = editors.map( - ({ node }) => _omit(node, ['selected']) as TagMaintainersNodeTagEditor - ) - cacheData.node.editors = [...currEditors, ...newEditors] - break - } - case 'remove': { - const newEditors = currEditors.filter( - (editor) => !editors.includes(editor.id) - ) - cacheData.node.editors = newEditors - break - } - } - - cache.writeQuery({ - query: TAG_MAINTAINERS, - variables, - data: cacheData, - }) - } catch (e) { - console.error(e) - } -} diff --git a/src/components/TagDigest/Buttons/FollowButton/Follow.tsx b/src/components/TagDigest/Buttons/FollowButton/Follow.tsx index 90bec0163c..d51319ec50 100644 --- a/src/components/TagDigest/Buttons/FollowButton/Follow.tsx +++ b/src/components/TagDigest/Buttons/FollowButton/Follow.tsx @@ -8,10 +8,10 @@ import { } from '~/common/enums' import { Button, TextIcon, useMutation, ViewerContext } from '~/components' import { updateViewerFollowingTagCount } from '~/components/GQL' -import TOGGLE_FOLLOW_TAG from '~/components/GQL/mutations/toggleFollowTag' +import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { TagDigestFollowButtonPrivateFragment, - ToggleFollowTagMutation, + ToggleBookmarkTagMutation, } from '~/gql/graphql' interface Props { @@ -21,12 +21,12 @@ interface Props { const Follow = ({ tag }: Props) => { const viewer = useContext(ViewerContext) - const [follow] = useMutation(TOGGLE_FOLLOW_TAG, { + const [follow] = useMutation(TOGGLE_BOOKMARK_TAG, { variables: { id: tag.id, enabled: true }, optimisticResponse: !_isNil(tag.id) && !_isNil(tag.isFollower) ? { - toggleFollowTag: { + toggleBookmarkTag: { id: tag.id, isFollower: true, __typename: 'Tag', diff --git a/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx b/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx index b83fc1b095..a83e9509a1 100644 --- a/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx +++ b/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx @@ -4,10 +4,10 @@ import { FormattedMessage } from 'react-intl' import { Button, TextIcon, useMutation } from '~/components' import { updateViewerFollowingTagCount } from '~/components/GQL' -import TOGGLE_FOLLOW_TAG from '~/components/GQL/mutations/toggleFollowTag' +import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { TagDigestFollowButtonPrivateFragment, - ToggleFollowTagMutation, + ToggleBookmarkTagMutation, } from '~/gql/graphql' interface UnfollowTagProps { @@ -16,22 +16,25 @@ interface UnfollowTagProps { const Unfollow = ({ tag }: UnfollowTagProps) => { const [hover, setHover] = useState(false) - const [unfollow] = useMutation(TOGGLE_FOLLOW_TAG, { - variables: { id: tag.id, enabled: false }, - optimisticResponse: - !_isNil(tag.id) && !_isNil(tag.isFollower) - ? { - toggleFollowTag: { - id: tag.id, - isFollower: false, - __typename: 'Tag', - }, - } - : undefined, - update: (cache) => { - updateViewerFollowingTagCount({ cache, type: 'decrement' }) - }, - }) + const [unfollow] = useMutation( + TOGGLE_BOOKMARK_TAG, + { + variables: { id: tag.id, enabled: false }, + optimisticResponse: + !_isNil(tag.id) && !_isNil(tag.isFollower) + ? { + toggleBookmarkTag: { + id: tag.id, + isFollower: false, + __typename: 'Tag', + }, + } + : undefined, + update: (cache) => { + updateViewerFollowingTagCount({ cache, type: 'decrement' }) + }, + } + ) return (
    - )} - - ) -} - -const Maintainers = ({ id, isOwner }: Props) => { - const { data, loading, error } = useQuery( - TAG_MAINTAINERS, - { - variables: { id }, - notifyOnNetworkStatusChange: true, - } - ) - - if (loading) { - return - } - - if (error) { - return - } - - if (data?.node?.__typename !== 'Tag') { - return null - } - - const tag = data.node - const editors = tag.editors || [] - - const isHavingEditors = editors.length > 0 - - return ( - <> - {tag.owner && ( - <> -
    -
    - -
    - {isOwner && ( -
    - -
    - )} -
    -
    - -
    - - )} - - {isHavingEditors && ( - <> -
    -
    - - ({editors.length}) -
    -
    -
      - {editors.map((editor) => ( -
    • - -
    • - ))} -
    - - )} - - ) -} - -export default Maintainers diff --git a/src/views/TagDetail/Community/Participants/gql.ts b/src/views/TagDetail/Community/Participants/gql.ts deleted file mode 100644 index 59119e0e9c..0000000000 --- a/src/views/TagDetail/Community/Participants/gql.ts +++ /dev/null @@ -1,29 +0,0 @@ -import gql from 'graphql-tag' - -import { UserDigest } from '~/components/UserDigest' - -export default gql` - query TagParticipants($id: ID!, $after: String) { - node(input: { id: $id }) { - ... on Tag { - id - participants(input: { first: 10, after: $after }) { - totalCount - pageInfo { - startCursor - endCursor - hasNextPage - } - edges { - cursor - node { - ...UserDigestRichUserPublic - } - } - } - __typename - } - } - } - ${UserDigest.Rich.fragments.user.public} -` diff --git a/src/views/TagDetail/Community/Participants/index.tsx b/src/views/TagDetail/Community/Participants/index.tsx deleted file mode 100644 index 3d4309f99a..0000000000 --- a/src/views/TagDetail/Community/Participants/index.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { NetworkStatus } from 'apollo-client' -import { FormattedMessage } from 'react-intl' - -import { analytics, mergeConnections } from '~/common/utils' -import { - InfiniteScroll, - List, - QueryError, - SpinnerBlock, - usePublicQuery, - UserDigest, -} from '~/components' -import { TagParticipantsQuery } from '~/gql/graphql' - -import styles from '../styles.module.css' -import TAG_PARTICIPANTS from './gql' - -interface Props { - id: string -} - -const Participants = ({ id }: Props) => { - const { data, loading, error, fetchMore, networkStatus } = - usePublicQuery(TAG_PARTICIPANTS, { - variables: { id }, - notifyOnNetworkStatusChange: true, - }) - - // pagination - const connectionPath = 'node.participants' - const { totalCount, edges, pageInfo } = - (data?.node?.__typename === 'Tag' && - data.node.participants && - data.node.participants) || - {} - const isNewLoading = - [NetworkStatus.loading, NetworkStatus.setVariables].indexOf( - networkStatus - ) >= 0 - - // load next page - const loadMore = async () => { - analytics.trackEvent('load_more', { - type: 'tag_detail_community', - location: edges?.length || 0, - }) - - await fetchMore({ - variables: { after: pageInfo?.endCursor }, - updateQuery: (previousResult, { fetchMoreResult }) => - mergeConnections({ - oldData: previousResult, - newData: fetchMoreResult, - path: connectionPath, - }), - }) - } - - if (loading && (!edges || isNewLoading)) { - return - } - - if (error) { - return - } - - if (!edges || edges.length <= 0 || !pageInfo) { - return null - } - - const count = totalCount || 0 - if (count === 0) { - return null - } - - return ( - <> -
    -
    - - ({count}) -
    -
    - - - - {(edges || []).map(({ node, cursor }, i) => ( - - - analytics.trackEvent('click_feed', { - type: 'tag_detail_community', - contentType: 'user', - location: i, - id: node.id, - }) - } - /> - - ))} - - - - ) -} - -export default Participants diff --git a/src/views/TagDetail/Community/index.tsx b/src/views/TagDetail/Community/index.tsx deleted file mode 100644 index 17bfa212e1..0000000000 --- a/src/views/TagDetail/Community/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Layout } from '~/components' - -import Maintainers from './Maintainers' -import Participants from './Participants' - -interface Props { - id: string - - isOwner: boolean -} - -const Community = ({ id, isOwner }: Props) => { - return ( - - - - - ) -} - -export default Community diff --git a/src/views/TagDetail/Community/styles.module.css b/src/views/TagDetail/Community/styles.module.css deleted file mode 100644 index 7056e1ba8a..0000000000 --- a/src/views/TagDetail/Community/styles.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.category { - @mixin flex-center-space-between; - - padding: var(--sp8) 0; - font-size: var(--text15); - font-weight: var(--font-medium); -} - -.count { - margin-left: var(--sp8); - color: var(--color-grey-dark); -} diff --git a/src/views/TagDetail/Cover/index.tsx b/src/views/TagDetail/Cover/index.tsx deleted file mode 100644 index 7ac82e91d0..0000000000 --- a/src/views/TagDetail/Cover/index.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import classNames from 'classnames' -import gql from 'graphql-tag' - -import { ReactComponent as IconHashTag } from '@/public/static/icons/24px/hashtag.svg' -import IMAGE_TAG_COVER from '@/public/static/images/tag-cover.png' -import { Cover } from '~/components' -import { Icon, TextIcon } from '~/components' -import { CoverTagFragment } from '~/gql/graphql' - -import styles from './styles.module.css' - -const TagCover = ({ tag }: { tag: CoverTagFragment }) => { - const titleClasses = classNames({ - [styles.title]: true, - [styles.mask]: !!tag.cover, - }) - - return ( - -
    -
    - - } - placement="right" - allowUserSelect - > - {tag.content} - - -
    -
    -
    - ) -} - -TagCover.fragments = { - tag: gql` - fragment CoverTag on Tag { - id - cover - content - numArticles - numAuthors - } - fragment DigestTag on Tag { - id - content - numArticles - numAuthors - } - `, -} - -export default TagCover diff --git a/src/views/TagDetail/Cover/styles.module.css b/src/views/TagDetail/Cover/styles.module.css deleted file mode 100644 index 1adddde5ad..0000000000 --- a/src/views/TagDetail/Cover/styles.module.css +++ /dev/null @@ -1,51 +0,0 @@ -.cover { - position: relative; - - & img { - @mixin object-fit-cover; - - background-color: var(--color-matters-green); - } - - &::after { - display: block; - padding-bottom: 46.93%; - content: ''; - - @media (--sm-up) { - padding-bottom: 30.14%; - } - } -} - -.title { - @mixin expand-to-container; - - & .content { - position: absolute; - right: var(--sp16); - bottom: var(--sp24); - left: var(--sp16); - line-height: 1; - } - - &.mask { - background: rgb(0 0 0 / 35%); - } -} - -.tag { - & .name { - @mixin line-clamp; - @mixin fix-cropped-letters; - - line-height: inherit; - } - - display: inline-flex; - line-height: 1.5rem; - - & svg { - margin-right: var(--sp2); - } -} diff --git a/src/views/TagDetail/DropdownActions/index.tsx b/src/views/TagDetail/DropdownActions/index.tsx deleted file mode 100644 index 802faa7224..0000000000 --- a/src/views/TagDetail/DropdownActions/index.tsx +++ /dev/null @@ -1,278 +0,0 @@ -import _isEmpty from 'lodash/isEmpty' -import _pickBy from 'lodash/pickBy' -import { useContext } from 'react' -import { FormattedMessage, useIntl } from 'react-intl' - -import { ReactComponent as IconCircleMinus } from '@/public/static/icons/24px/circle-minus.svg' -import { ReactComponent as IconCirclePlus } from '@/public/static/icons/24px/circle-plus.svg' -import { ReactComponent as IconEdit } from '@/public/static/icons/24px/edit.svg' -import { ReactComponent as IconProfile } from '@/public/static/icons/24px/profile.svg' -import { ReactComponent as IconSettings } from '@/public/static/icons/24px/settings.svg' -import { REFETCH_TAG_DETAIL_ARTICLES } from '~/common/enums' -import { - Button, - Dropdown, - EditTagDialog, - EditTagDialogProps, - Icon, - Menu, - TagEditorDialog, - TagEditorDialogProps, - TagLeaveDialog, - TagLeaveDialogProps, - toast, - useMutation, - ViewerContext, - withDialog, -} from '~/components' -import { - SearchSelectDialog, - SearchSelectDialogProps, -} from '~/components/Dialogs/SearchSelectDialog' -import { SearchSelectNode } from '~/components/Forms/SearchSelectForm' -import { updateTagArticlesCount } from '~/components/GQL' -import ADD_ARTICLES_TAGS from '~/components/GQL/mutations/addArticlesTags' -import { AddArticlesTagsMutation, TagFragmentFragment } from '~/gql/graphql' -interface DropdownActionsProps { - // id: string - isOwner: boolean - isEditor: boolean - isMaintainer: boolean - tag: TagFragmentFragment -} - -interface DialogProps { - openTagAddSelectedArticlesDialog: () => void - openEditTagDialog: () => void - openTagEditorDialog: () => void - openTagLeaveDialog: () => void -} - -interface Controls { - hasEditTag: boolean - hasAddSelectedArticle: boolean - hasManageCommunity: boolean - hasTagLeave: boolean -} - -type BaseDropdownActionsProps = DropdownActionsProps & DialogProps & Controls - -const BaseDropdownActions = ({ - hasEditTag, - hasAddSelectedArticle, - hasManageCommunity, - hasTagLeave, - - openTagAddSelectedArticlesDialog, - openEditTagDialog, - openTagEditorDialog, - openTagLeaveDialog, -}: BaseDropdownActionsProps) => { - const intl = useIntl() - const Content = () => ( - - {hasEditTag && ( - } - icon={} - onClick={openEditTagDialog} - ariaHasPopup="dialog" - /> - )} - {hasAddSelectedArticle && ( - - } - icon={} - onClick={openTagAddSelectedArticlesDialog} - ariaHasPopup="dialog" - /> - )} - {hasManageCommunity && ( - - } - icon={} - onClick={openTagEditorDialog} - ariaHasPopup="dialog" - /> - )} - {hasTagLeave && ( - - } - icon={} - onClick={openTagLeaveDialog} - ariaHasPopup="dialog" - /> - )} - - ) - - return ( - }> - {({ openDropdown, ref }) => ( - - )} - - ) -} - -const DropdownActions = (props: DropdownActionsProps) => { - const viewer = useContext(ViewerContext) - const { tag } = props - - const intl = useIntl() - /** - * Data - */ - const [add, { loading }] = - useMutation(ADD_ARTICLES_TAGS) - const addArticlesToTag = - (selected: boolean) => async (articles: SearchSelectNode[]) => { - const articleIds = articles.map((article) => article.id) - - await add({ - variables: { id: tag.id, articles: articleIds, selected }, - update: (cache, { data }) => { - if (selected) { - const newCount = data?.addArticlesTags?.articles?.totalCount || 0 - const oldCount = tag.articles.totalCount || 0 - updateTagArticlesCount({ - cache, - id: tag.id, - count: newCount - oldCount, - type: 'increment', - }) - } - }, - }) - - toast.success({ - message: intl.formatMessage({ - defaultMessage: 'Tags added', - id: 'UjKkhq', - description: 'src/views/TagDetail/DropdownActions/index.tsx', - }), - }) - - window.dispatchEvent( - new CustomEvent(REFETCH_TAG_DETAIL_ARTICLES, { - detail: { - event: 'add', - differences: articles.length, - }, - }) - ) - } - - const forbid = () => { - toast.error({ - message: ( - - ), - }) - return - } - - const controls = { - hasEditTag: props.isOwner, - hasAddSelectedArticle: props.isMaintainer, - hasManageCommunity: props.isOwner, - hasTagLeave: props.isOwner || props.isEditor, - } - - if (_isEmpty(_pickBy(controls))) { - return null - } - - const WithEditTag = withDialog>( - BaseDropdownActions, - EditTagDialog, - { ...props.tag }, - ({ openDialog }) => { - return { - ...props, - ...controls, - openEditTagDialog: viewer.isFrozen ? forbid : openDialog, - } - } - ) - const WithSearchSelect = withDialog< - Omit - >( - WithEditTag, - SearchSelectDialog, - { - title: ( - - ), - hint: ( - - ), - searchType: 'Article', - onSave: addArticlesToTag(true), - saving: loading, - }, - ({ openDialog }) => ({ - openTagAddSelectedArticlesDialog: viewer.isFrozen ? forbid : openDialog, - }) - ) - const WithTagLeave = withDialog>( - WithSearchSelect, - TagLeaveDialog, - { ...props, id: tag.id }, - ({ openDialog }) => ({ - openTagLeaveDialog: viewer.isFrozen ? forbid : openDialog, - }) - ) - const WithTagEditor = withDialog>( - WithTagLeave, - TagEditorDialog, - { ...props, id: tag.id }, - ({ openDialog }) => ({ - openTagEditorDialog: viewer.isFrozen ? forbid : openDialog, - }) - ) - - return -} - -export default DropdownActions diff --git a/src/views/TagDetail/DropdownActions/styles.module.css b/src/views/TagDetail/DropdownActions/styles.module.css deleted file mode 100644 index b1b02153c9..0000000000 --- a/src/views/TagDetail/DropdownActions/styles.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.container { - margin-left: var(--sp12); -} diff --git a/src/views/TagDetail/Followers/index.tsx b/src/views/TagDetail/Followers/index.tsx deleted file mode 100644 index 44ff57e3f9..0000000000 --- a/src/views/TagDetail/Followers/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { FormattedMessage } from 'react-intl' - -import { numAbbr } from '~/common/utils' -import tagFragments from '~/components/GQL/fragments/tag' -import { FollowersTagFragment } from '~/gql/graphql' - -import styles from './styles.module.css' - -interface FollowersProps { - tag: FollowersTagFragment -} - -const Followers = ({ tag }: FollowersProps) => { - const { totalCount } = tag.followers || { - edges: [], - totalCount: 0, - } - - return ( -
    -
    - {numAbbr(totalCount)} - -   - - -
    -
    - ) -} - -Followers.fragments = { - tag: tagFragments.followers, -} -export default Followers diff --git a/src/views/TagDetail/Followers/styles.module.css b/src/views/TagDetail/Followers/styles.module.css deleted file mode 100644 index 54802239b0..0000000000 --- a/src/views/TagDetail/Followers/styles.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.container { - @mixin flex-center-start; -} - -.count { - @mixin inline-flex-center-all; - - font-size: var(--text14); - line-height: 1; - color: var(--color-grey-darker); - - & b { - color: var(--color-black); - } -} diff --git a/src/views/TagDetail/Owner/index.tsx b/src/views/TagDetail/Owner/index.tsx deleted file mode 100644 index 220d51b9df..0000000000 --- a/src/views/TagDetail/Owner/index.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { useContext } from 'react' -import { FormattedMessage } from 'react-intl' - -import { ReactComponent as IconAvatarEmpty } from '@/public/static/icons/24px/avatar-empty.svg' -import { - Button, - Icon, - TagAdoptionDialog, - TextIcon, - toast, - UserDigest, - ViewerContext, -} from '~/components' -import { TagFragmentFragment } from '~/gql/graphql' - -import styles from './styles.module.css' - -const Owner = ({ tag }: { tag: TagFragmentFragment }) => { - const viewer = useContext(ViewerContext) - - const forbid = () => { - toast.error({ - message: ( - - ), - }) - } - - if (!tag) { - return null - } - - if (!tag.owner) { - return ( -
    -
    - } - color="greyDark" - size={15} - spacing={8} - > - - -
    -
    - - {({ openDialog }) => ( - - )} - -
    -
    - ) - } - - return ( -
    -
    - - - - - -
    -
    {/* editos */}
    -
    - ) -} - -export default Owner diff --git a/src/views/TagDetail/Owner/styles.module.css b/src/views/TagDetail/Owner/styles.module.css deleted file mode 100644 index 8bb1982fba..0000000000 --- a/src/views/TagDetail/Owner/styles.module.css +++ /dev/null @@ -1,20 +0,0 @@ -.container { - @mixin flex-center-space-between; - - padding: var(--sp8) var(--sp16); - margin-top: var(--sp16); - background: var(--color-grey-lighter); - border-radius: var(--sp8); -} - -.left { - @mixin flex-center-start; - - & > * + * { - margin-left: var(--sp8); - } -} - -.right { - @mixin flex-center-end; -} diff --git a/src/views/TagDetail/gql.ts b/src/views/TagDetail/gql.ts index 7cacd1e440..5d4741011e 100644 --- a/src/views/TagDetail/gql.ts +++ b/src/views/TagDetail/gql.ts @@ -4,43 +4,23 @@ import { UserDigest } from '~/components/UserDigest' import ArticlesCount from './ArticlesCount' import { TagDetailButtons } from './Buttons' -import Followers from './Followers' const tagFragment = gql` fragment TagFragment on Tag { id content - cover - description numArticles numAuthors - creator { - id - ...UserDigestMiniUser - } - editors { - id - ...UserDigestMiniUser - } - owner { - id - ...UserDigestMiniUser - } - selectedArticles: articles(input: { first: 0, selected: true }) { + selectedArticles: articles(input: { first: 0 }) { totalCount } - isOfficial - ...FollowersTag ...ArticleCountTag - ...FollowButtonTagPrivate recommended(input: {}) { edges { cursor node { id content - description - cover numArticles numAuthors } @@ -48,7 +28,6 @@ const tagFragment = gql` } } ${UserDigest.Mini.fragments.user} - ${Followers.fragments.tag} ${ArticlesCount.fragments.tag} ${TagDetailButtons.FollowButton.fragments.tag.private} ` diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index f2c1b2fe93..18060773c5 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -1,26 +1,17 @@ -import dynamic from 'next/dynamic' import { useContext, useEffect, useState } from 'react' import { FormattedMessage } from 'react-intl' import IMAGE_TAG_COVER from '@/public/static/images/tag-cover.png' import { ERROR_CODES } from '~/common/enums' -import { - fromGlobalId, - normalizeTag, - stripSpaces, - toGlobalId, - toPath, -} from '~/common/utils' +import { fromGlobalId, normalizeTag, toGlobalId, toPath } from '~/common/utils' import { EmptyLayout, EmptyTag, - Expandable, Head, Layout, SegmentedTabs, SpinnerBlock, Throw404, - useFeatures, usePublicQuery, useRoute, ViewerContext, @@ -35,30 +26,19 @@ import { import TagDetailArticles from './Articles' import ArticlesCount from './ArticlesCount' import { TagDetailButtons } from './Buttons' -import TagCover from './Cover' -import DropdownActions from './DropdownActions' -import Followers from './Followers' import { TAG_DETAIL_BY_SEARCH, TAG_DETAIL_PRIVATE, TAG_DETAIL_PUBLIC, } from './gql' -import Owner from './Owner' import RelatedTags from './RelatedTags' import styles from './styles.module.css' -const DynamicCommunity = dynamic(() => import('./Community'), { - ssr: false, - loading: () => , -}) - const validTagFeedTypes = ['hottest', 'latest', 'selected', 'creators'] as const type TagFeedType = (typeof validTagFeedTypes)[number] const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const { router } = useRoute() - const viewer = useContext(ViewerContext) - const features = useFeatures() // feed type const { getQuery, setQuery } = useRoute() @@ -104,14 +84,8 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { } }, []) - // define permission - const isOwner = tag?.owner?.id === viewer.id - const isEditor = (tag?.editors || []).some((t) => t.id === viewer.id) - const isMaintainer = isOwner || isEditor || viewer.isAdmin // Matty - const title = '#' + normalizeTag(tag.content) const keywords = tag.content.split(/\s+/).filter(Boolean).map(normalizeTag) - const description = stripSpaces(tag.description) const path = toPath({ page: 'tagDetail', tag }) /** @@ -128,12 +102,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { title={title} tags={title.endsWith(tag.content) ? undefined : keywords} /> - } @@ -145,34 +113,22 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { // description={tag.description} title={title} path={qsType ? `${path.href}?type=${qsType}` : path.href} - description={description} keywords={keywords} // add top10 most using author names? - image={ - tag.cover || - `//${process.env.NEXT_PUBLIC_SITE_DOMAIN}${IMAGE_TAG_COVER.src}` - } + image={`//${process.env.NEXT_PUBLIC_SITE_DOMAIN}${IMAGE_TAG_COVER.src}`} jsonLdData={{ '@context': 'https://schema.org', '@type': 'ItemList', // should follow with some recent articles under 'itemListElement' name: title, - description, keywords, - image: - tag.cover || - `https://${process.env.NEXT_PUBLIC_SITE_DOMAIN}${IMAGE_TAG_COVER.src}`, + image: `https://${process.env.NEXT_PUBLIC_SITE_DOMAIN}${IMAGE_TAG_COVER.src}`, url: `https://${process.env.NEXT_PUBLIC_SITE_DOMAIN}/${path.href}`, // itemListElement: [...], }} /> - -
    - {features.tag_adoption && } -
    -
    @@ -180,17 +136,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => {
    - - {tag.description && ( - -

    {tag.description}

    -
    - )} @@ -228,8 +173,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { {(isHottest || isLatest || isSelected) && ( )} - - {isCreators && } ) } diff --git a/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx b/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx index 7fd265be03..fcebbeaafa 100644 --- a/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx +++ b/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx @@ -115,7 +115,6 @@ const TagsFeed = () => { spacing={[12, 16]} bgColor="none" bgActiveColor="greyLighter" - hasDesc hasFollow /> diff --git a/tests/helpers/poms/articleDetail.ts b/tests/helpers/poms/articleDetail.ts index e95cf587d7..1370785ba7 100644 --- a/tests/helpers/poms/articleDetail.ts +++ b/tests/helpers/poms/articleDetail.ts @@ -177,7 +177,7 @@ export class ArticleDetailPage { await Promise.all([ waitForAPIResponse({ page: this.page, - path: 'data.toggleSubscribeArticle.subscribed', + path: 'data.toggleBookmarkArticle.followed', }), this.toolbarBookmarkButton.click(), ]) From 009327ba5f9a7edbcc382cc5c1630f5f84d4ab89 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:33:38 +0700 Subject: [PATCH 18/69] feat(tag): remove unused --- .../Follow.tsx => BookmarkButton/Bookmark.tsx} | 10 +++++----- .../Unfollow.tsx => BookmarkButton/Unbookmark.tsx} | 10 +++++----- .../{FollowButton => BookmarkButton}/index.tsx | 14 +++++++------- src/views/TagDetail/Buttons/index.tsx | 4 ++-- src/views/TagDetail/gql.ts | 12 +++++------- src/views/TagDetail/index.tsx | 2 +- 6 files changed, 25 insertions(+), 27 deletions(-) rename src/views/TagDetail/Buttons/{FollowButton/Follow.tsx => BookmarkButton/Bookmark.tsx} (90%) rename src/views/TagDetail/Buttons/{FollowButton/Unfollow.tsx => BookmarkButton/Unbookmark.tsx} (87%) rename src/views/TagDetail/Buttons/{FollowButton => BookmarkButton}/index.tsx (52%) diff --git a/src/views/TagDetail/Buttons/FollowButton/Follow.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx similarity index 90% rename from src/views/TagDetail/Buttons/FollowButton/Follow.tsx rename to src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx index de1ec98034..d9a2e4871c 100644 --- a/src/views/TagDetail/Buttons/FollowButton/Follow.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx @@ -16,15 +16,15 @@ import { } from '~/components' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { - FollowButtonTagPrivateFragment, + BookmarkButtonTagPrivateFragment, ToggleBookmarkTagMutation, } from '~/gql/graphql' -interface FollowProps { - tag: FollowButtonTagPrivateFragment +interface BookmarkProps { + tag: BookmarkButtonTagPrivateFragment } -const Follow = ({ tag }: FollowProps) => { +const Bookmark = ({ tag }: BookmarkProps) => { const viewer = useContext(ViewerContext) const [follow] = useMutation(TOGGLE_BOOKMARK_TAG, { variables: { id: tag.id, enabled: true }, @@ -69,4 +69,4 @@ const Follow = ({ tag }: FollowProps) => { ) } -export default Follow +export default Bookmark diff --git a/src/views/TagDetail/Buttons/FollowButton/Unfollow.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx similarity index 87% rename from src/views/TagDetail/Buttons/FollowButton/Unfollow.tsx rename to src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx index fa74a187e6..5121f177d2 100644 --- a/src/views/TagDetail/Buttons/FollowButton/Unfollow.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx @@ -5,15 +5,15 @@ import { FormattedMessage } from 'react-intl' import { Button, TextIcon, useMutation } from '~/components' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { - FollowButtonTagPrivateFragment, + BookmarkButtonTagPrivateFragment, ToggleBookmarkTagMutation, } from '~/gql/graphql' -interface UnfollowTagProps { - tag: FollowButtonTagPrivateFragment +interface UnbookmarkTagProps { + tag: BookmarkButtonTagPrivateFragment } -const Unfollow = ({ tag }: UnfollowTagProps) => { +const Unbookmark = ({ tag }: UnbookmarkTagProps) => { const [hover, setHover] = useState(false) const [unfollow] = useMutation( TOGGLE_BOOKMARK_TAG, @@ -53,4 +53,4 @@ const Unfollow = ({ tag }: UnfollowTagProps) => { ) } -export default Unfollow +export default Unbookmark diff --git a/src/views/TagDetail/Buttons/FollowButton/index.tsx b/src/views/TagDetail/Buttons/BookmarkButton/index.tsx similarity index 52% rename from src/views/TagDetail/Buttons/FollowButton/index.tsx rename to src/views/TagDetail/Buttons/BookmarkButton/index.tsx index 3a581b255b..0ec96f02c4 100644 --- a/src/views/TagDetail/Buttons/FollowButton/index.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/index.tsx @@ -1,18 +1,18 @@ import gql from 'graphql-tag' -import { FollowButtonTagPrivateFragment } from '~/gql/graphql' +import { BookmarkButtonTagPrivateFragment } from '~/gql/graphql' -import Follow from './Follow' -import Unfollow from './Unfollow' +import Bookmark from './Bookmark' +import Unbookmark from './Unbookmark' interface FollowButtonProps { - tag: FollowButtonTagPrivateFragment + tag: BookmarkButtonTagPrivateFragment } const fragments = { tag: { private: gql` - fragment FollowButtonTagPrivate on Tag { + fragment BookmarkButtonTagPrivate on Tag { id isFollower } @@ -22,9 +22,9 @@ const fragments = { const FollowButton = ({ tag }: FollowButtonProps) => { if (tag.isFollower) { - return + return } else { - return + return } } diff --git a/src/views/TagDetail/Buttons/index.tsx b/src/views/TagDetail/Buttons/index.tsx index cd045c6a17..1044007be3 100644 --- a/src/views/TagDetail/Buttons/index.tsx +++ b/src/views/TagDetail/Buttons/index.tsx @@ -1,5 +1,5 @@ -import FollowButton from './FollowButton' +import BookmarkButton from './BookmarkButton' export const TagDetailButtons = { - FollowButton, + BookmarkButton, } diff --git a/src/views/TagDetail/gql.ts b/src/views/TagDetail/gql.ts index 5d4741011e..6df71da98f 100644 --- a/src/views/TagDetail/gql.ts +++ b/src/views/TagDetail/gql.ts @@ -1,7 +1,5 @@ import gql from 'graphql-tag' -import { UserDigest } from '~/components/UserDigest' - import ArticlesCount from './ArticlesCount' import { TagDetailButtons } from './Buttons' @@ -15,7 +13,8 @@ const tagFragment = gql` totalCount } ...ArticleCountTag - recommended(input: {}) { + ...BookmarkButtonTagPrivate + recommended(input: { first: 10 }) { edges { cursor node { @@ -27,9 +26,8 @@ const tagFragment = gql` } } } - ${UserDigest.Mini.fragments.user} ${ArticlesCount.fragments.tag} - ${TagDetailButtons.FollowButton.fragments.tag.private} + ${TagDetailButtons.BookmarkButton.fragments.tag.private} ` export const TAG_DETAIL_PUBLIC = gql` @@ -64,9 +62,9 @@ export const TAG_DETAIL_PRIVATE = gql` node(input: { id: $id }) { ... on Tag { id - ...FollowButtonTagPrivate + ...BookmarkButtonTagPrivate } } } - ${TagDetailButtons.FollowButton.fragments.tag.private} + ${TagDetailButtons.BookmarkButton.fragments.tag.private} ` diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index 18060773c5..9abd052b77 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -133,7 +133,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => {
    - +
    From 4c662195271efa7aeece50a8072f25429fa38583 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:35:52 +0700 Subject: [PATCH 19/69] feat(tag): remove unused --- src/views/TagDetail/Articles/index.tsx | 7 +------ src/views/TagDetail/index.tsx | 25 +------------------------ 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/src/views/TagDetail/Articles/index.tsx b/src/views/TagDetail/Articles/index.tsx index 9ef95e2a45..a6a9009591 100644 --- a/src/views/TagDetail/Articles/index.tsx +++ b/src/views/TagDetail/Articles/index.tsx @@ -34,7 +34,6 @@ const TagDetailArticles = ({ tag, feedType }: TagArticlesProps) => { const viewer = useContext(ViewerContext) const feed = useRef(feedType) - const isSelected = feedType === 'selected' const isHottest = feedType === 'hottest' /** @@ -101,11 +100,7 @@ const TagDetailArticles = ({ tag, feedType }: TagArticlesProps) => { }, [!!edges, loading, feedType, viewer.id]) // load next page - const trackingType = isHottest - ? 'tag_detail_hottest' - : isSelected - ? 'tag_detail_selected' - : 'tag_detail_latest' + const trackingType = isHottest ? 'tag_detail_hottest' : 'tag_detail_latest' const loadMore = async () => { analytics.trackEvent('load_more', { type: trackingType, diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index 9abd052b77..caebe6c95d 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -62,17 +62,10 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { ) }, [qsType]) - const isSelected = feedType === 'selected' const isHottest = feedType === 'hottest' const isLatest = feedType === 'latest' - const isCreators = feedType === 'creators' useEffect(() => { - // if selected feed is empty, switch to hottest feed - if (!hasSelectedFeed && isSelected) { - changeFeed('hottest') - } - // backward compatible with `/tags/:globalId:` const newPath = toPath({ page: 'tagDetail', @@ -152,25 +145,9 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { > - - {hasSelectedFeed && ( - changeFeed('selected')} - > - - - )} - - changeFeed('creators')} - > - -
    - {(isHottest || isLatest || isSelected) && ( + {(isHottest || isLatest) && ( )} From 81d85c73388fb982168d43856e4ab96bed5cea1b Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:28:41 +0800 Subject: [PATCH 20/69] feat(Tags): revise all tag pages --- src/views/Tags/gql.ts | 2 +- src/views/Tags/styles.module.css | 42 ++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/views/Tags/gql.ts b/src/views/Tags/gql.ts index ed4431ca8d..23261429a9 100644 --- a/src/views/Tags/gql.ts +++ b/src/views/Tags/gql.ts @@ -7,7 +7,7 @@ export const ALL_TAGS_HOTTEST = gql` viewer @connection(key: "viewerAllTagsHottest") { id recommendation { - tags(input: { first: 20, after: $after }) { + tags(input: { first: 30, after: $after }) { totalCount pageInfo { startCursor diff --git a/src/views/Tags/styles.module.css b/src/views/Tags/styles.module.css index 7cf203246b..5a3c1891e7 100644 --- a/src/views/Tags/styles.module.css +++ b/src/views/Tags/styles.module.css @@ -1,30 +1,40 @@ .tags { - /* FIXME: top header overlay by sticky tabs */ + margin-top: var(--sp24); - /* margin-top: 1px; */ + @media (--sm-up) { + margin-top: var(--sp32); + } } .list { - @media (--lg-up) { - display: grid; - grid-template-columns: repeat(2, 1fr); - - /* margin-top: calc(var(--sp16) * -1); */ - } + display: flex; + flex-wrap: wrap; & .listItem { - position: relative; - padding: var(--sp8) 0; + @mixin border-bottom-grey-light; - @media (--lg-up) { - padding: var(--sp16) 0; + position: relative; + flex: 0 0 50%; + padding-bottom: var(--sp20); + margin-bottom: var(--sp20); + border-style: dashed; + } - &:nth-child(2n) { - margin-left: var(--sp4); + @media (--sm-down) { + & .listItem { + &:nth-child(2n + 1) { + padding-right: var(--sp16); } + } + } - &:nth-child(2n + 1) { - margin-right: var(--sp24); + @media (--sm-up) { + & .listItem { + flex: 0 0 33.3333%; + + &:nth-child(3n + 1), + &:nth-child(3n + 2) { + padding-right: var(--sp16); } } } From 94d743f0bb80b9bdc0c41a39989d865e4410223d Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:50:56 +0800 Subject: [PATCH 21/69] fix(Tags): fix layout --- src/views/Tags/styles.module.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/views/Tags/styles.module.css b/src/views/Tags/styles.module.css index 5a3c1891e7..12bde92ba2 100644 --- a/src/views/Tags/styles.module.css +++ b/src/views/Tags/styles.module.css @@ -18,6 +18,10 @@ padding-bottom: var(--sp20); margin-bottom: var(--sp20); border-style: dashed; + + &:last-child { + flex-grow: 1; + } } @media (--sm-down) { From d2ccd27735f11b64ee69b131d9a14a3015918fcd Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:31:13 +0700 Subject: [PATCH 22/69] feat: remove unused translations --- lang/default.json | 3 --- lang/en.json | 3 --- lang/zh-Hans.json | 3 --- lang/zh-Hant.json | 3 --- 4 files changed, 12 deletions(-) diff --git a/lang/default.json b/lang/default.json index 320b760aaa..72c1cf219c 100644 --- a/lang/default.json +++ b/lang/default.json @@ -1803,9 +1803,6 @@ "defaultMessage": "Broadcast sent", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "Creators" - }, "U+qEBM": { "defaultMessage": "Switch Network", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/en.json b/lang/en.json index a7068ee251..d09ec245bd 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1803,9 +1803,6 @@ "defaultMessage": "Broadcast sent", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "Creators" - }, "U+qEBM": { "defaultMessage": "Switch Network", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index a8f4d97d20..fb569f115e 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -1803,9 +1803,6 @@ "defaultMessage": "广播已送出", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "创作者" - }, "U+qEBM": { "defaultMessage": "切换网络", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index c5ad7aba33..143beed746 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -1803,9 +1803,6 @@ "defaultMessage": "廣播已送出", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "創作者" - }, "U+qEBM": { "defaultMessage": "切換網路", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" From a5d24936a59d935c58fc5adcdcade29f4f17a16b Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:18:28 +0800 Subject: [PATCH 23/69] feat(TagDetail): revise bookmark button --- lang/default.json | 3 -- lang/en.json | 3 -- lang/zh-Hans.json | 3 -- lang/zh-Hant.json | 3 -- .../Buttons/BookmarkButton/Bookmark.tsx | 23 +++++++------ .../Buttons/BookmarkButton/Unbookmark.tsx | 34 ++++++++----------- src/views/TagDetail/index.tsx | 4 +-- 7 files changed, 28 insertions(+), 45 deletions(-) diff --git a/lang/default.json b/lang/default.json index c626d33e31..a244548115 100644 --- a/lang/default.json +++ b/lang/default.json @@ -1807,9 +1807,6 @@ "defaultMessage": "Broadcast sent", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "Creators" - }, "U+qEBM": { "defaultMessage": "Switch Network", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/en.json b/lang/en.json index d0956e2439..a7d7ba58bb 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1807,9 +1807,6 @@ "defaultMessage": "Broadcast sent", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "Creators" - }, "U+qEBM": { "defaultMessage": "Switch Network", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 4e50d2b65a..874fbfe04d 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -1807,9 +1807,6 @@ "defaultMessage": "广播已送出", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "创作者" - }, "U+qEBM": { "defaultMessage": "切换网络", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index af5d280603..2789029c75 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -1807,9 +1807,6 @@ "defaultMessage": "廣播已送出", "description": "src/views/Circle/Broadcast/Broadcast.tsx" }, - "TzhzIH": { - "defaultMessage": "創作者" - }, "U+qEBM": { "defaultMessage": "切換網路", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx index d9a2e4871c..a5906162fc 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx @@ -1,8 +1,8 @@ import _isNil from 'lodash/isNil' import { useContext } from 'react' -import { FormattedMessage } from 'react-intl' +import { useIntl } from 'react-intl' -import { ReactComponent as IconPlus } from '@/public/static/icons/24px/plus.svg' +import { ReactComponent as IconSave } from '@/public/static/icons/24px/save.svg' import { OPEN_UNIVERSAL_AUTH_DIALOG, UNIVERSAL_AUTH_TRIGGER, @@ -10,7 +10,6 @@ import { import { Button, Icon, - TextIcon, useMutation, ViewerContext, } from '~/components' @@ -26,6 +25,7 @@ interface BookmarkProps { const Bookmark = ({ tag }: BookmarkProps) => { const viewer = useContext(ViewerContext) + const intl = useIntl() const [follow] = useMutation(TOGGLE_BOOKMARK_TAG, { variables: { id: tag.id, enabled: true }, optimisticResponse: @@ -55,16 +55,17 @@ const Bookmark = ({ tag }: BookmarkProps) => { return ( ) } diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx index 5121f177d2..5d844c6d27 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx @@ -1,8 +1,8 @@ import _isNil from 'lodash/isNil' -import { useState } from 'react' -import { FormattedMessage } from 'react-intl' +import { useIntl } from 'react-intl' -import { Button, TextIcon, useMutation } from '~/components' +import { ReactComponent as IconSave2 } from '@/public/static/icons/24px/save2.svg' +import { Button, Icon, useMutation } from '~/components' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { BookmarkButtonTagPrivateFragment, @@ -14,7 +14,7 @@ interface UnbookmarkTagProps { } const Unbookmark = ({ tag }: UnbookmarkTagProps) => { - const [hover, setHover] = useState(false) + const intl = useIntl() const [unfollow] = useMutation( TOGGLE_BOOKMARK_TAG, { @@ -34,22 +34,18 @@ const Unbookmark = ({ tag }: UnbookmarkTagProps) => { return ( + + ) } diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index bf4e34d857..f04e4c8a5d 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -123,9 +123,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { -
    - -
    +
    From 63982d3c9ef0564162873bdca8f91ed482372aab Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:39:06 +0800 Subject: [PATCH 24/69] feat(TagDetail): align spacing --- .../TagDetail/Buttons/BookmarkButton/Bookmark.tsx | 7 +------ .../Buttons/BookmarkButton/Unbookmark.tsx | 6 +++--- src/views/TagDetail/styles.module.css | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx index a5906162fc..5fbacf21d3 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx @@ -7,12 +7,7 @@ import { OPEN_UNIVERSAL_AUTH_DIALOG, UNIVERSAL_AUTH_TRIGGER, } from '~/common/enums' -import { - Button, - Icon, - useMutation, - ViewerContext, -} from '~/components' +import { Button, Icon, useMutation, ViewerContext } from '~/components' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { BookmarkButtonTagPrivateFragment, diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx index 5d844c6d27..a170834ce0 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx @@ -34,7 +34,7 @@ const Unbookmark = ({ tag }: UnbookmarkTagProps) => { return ( + ) } diff --git a/src/views/TagDetail/styles.module.css b/src/views/TagDetail/styles.module.css index e4aa04cc18..eb88e18ae2 100644 --- a/src/views/TagDetail/styles.module.css +++ b/src/views/TagDetail/styles.module.css @@ -2,7 +2,12 @@ @mixin flex-center-start; height: 2.25rem; /* 36px; */ + padding: 0 var(--sp16); margin: var(--sp32) 0; + + @media (--sm-up) { + padding: 0; + } } .info { @@ -11,11 +16,21 @@ @mixin flex-center-space-between; padding: var(--sp16) 0; + margin: 0 var(--sp16); + + @media (--sm-up) { + margin: 0; + } } .tabs { + padding: 0 var(--sp16); margin-top: var(--sp32); margin-bottom: var(--sp12); + + @media (--sm-up) { + padding: 0; + } } .buttons { From b403546d0d7df85b812752412a0188dca02dcb0a Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:48:36 +0700 Subject: [PATCH 25/69] fix(tag): fix tests --- src/common/enums/test.ts | 1 - .../DropdownActions/DropdownActions.test.tsx | 41 ------------------- src/components/TagDigest/Rich/Rich.test.tsx | 6 --- .../TagDigest/Sidebar/Sidebar.test.tsx | 6 --- src/components/TagDigest/Sidebar/index.tsx | 5 +-- src/stories/mocks/index.ts | 5 --- 6 files changed, 1 insertion(+), 63 deletions(-) diff --git a/src/common/enums/test.ts b/src/common/enums/test.ts index dde26d8eb6..c5634f3469 100644 --- a/src/common/enums/test.ts +++ b/src/common/enums/test.ts @@ -44,7 +44,6 @@ export enum TEST_ID { DIGEST_CIRCLE_MEMBER_COUNT = 'digest/circle/member-count', DIGEST_CIRCLE_ARTICLE_COUNT = 'digest/circle/article-count', DIGEST_CIRCLE_PRICE = 'digest/circle/price', - DIGEST_TAG_SIDEBAR_COVER = 'digest/tag/sidebar/cover', DIGEST_COLLECTION_FEED = 'digest/collection/feed', DIGEST_DRAFT_FEED = 'digest/draft/feed', // dialogs diff --git a/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx b/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx index 5ec21d4495..2d5f13a890 100644 --- a/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx +++ b/src/components/ArticleDigest/DropdownActions/DropdownActions.test.tsx @@ -190,47 +190,6 @@ describe('', () => { expect($archiveButton).toBeInTheDocument() }) - // hasSetTagSelected - // hasSetTagUnselected - // hasRemoveTag - it('should render tag buttons', async () => { - render( - - ) - - const $button = screen.getByLabelText('More Actions') - expect($button).toBeInTheDocument() - - // open menu - $button.click() - const $menu = screen.getByRole('menu') - expect($menu).toBeInTheDocument() - - // hasSetTagSelected - const $setTagSelectedBtn = screen.getByRole('menuitem', { - name: 'Add to Featured', - }) - expect($setTagSelectedBtn).toBeInTheDocument() - - // hasUnsetTagSelected - const $setTagUnselectedBtn = screen.getByRole('menuitem', { - name: 'Unpin from Trending', - }) - expect($setTagUnselectedBtn).toBeInTheDocument() - - // hasRemoveTag - const $removeTagBtn = screen.getByRole('menuitem', { - name: 'Remove Article', - }) - expect($removeTagBtn).toBeInTheDocument() - }) - // hasSetTopCollection // hasSetBottomCollection // hasAddCollection diff --git a/src/components/TagDigest/Rich/Rich.test.tsx b/src/components/TagDigest/Rich/Rich.test.tsx index 9b13310bb2..7511767274 100644 --- a/src/components/TagDigest/Rich/Rich.test.tsx +++ b/src/components/TagDigest/Rich/Rich.test.tsx @@ -20,9 +20,6 @@ describe('', () => { const $followButton = screen.getByText('Follow') expect($followButton).toBeInTheDocument() - - const $description = screen.getByText(MOCK_TAG.description) - expect($description).toBeInTheDocument() }) it('should render a TagDigest.Rich without description', () => { @@ -30,9 +27,6 @@ describe('', () => { const $digest = screen.getByTestId(TEST_ID.DIGEST_TAG_RICH) expect($digest).toBeInTheDocument() - - const $description = screen.queryByText(MOCK_TAG.description) - expect($description).not.toBeInTheDocument() }) it('should render a TagDigest.Rich without follow button', () => { diff --git a/src/components/TagDigest/Sidebar/Sidebar.test.tsx b/src/components/TagDigest/Sidebar/Sidebar.test.tsx index e36b6e87d0..beb3de4993 100644 --- a/src/components/TagDigest/Sidebar/Sidebar.test.tsx +++ b/src/components/TagDigest/Sidebar/Sidebar.test.tsx @@ -23,11 +23,5 @@ describe('', () => { const $authorCount = screen.getByText(MOCK_TAG.numAuthors) expect($authorCount).toBeInTheDocument() - - const $cover = screen.getByTestId(TEST_ID.DIGEST_TAG_SIDEBAR_COVER) - expect($cover).toBeInTheDocument() - mockRouter.push('/') - $cover.click() - expect(mockRouter.asPath).toContain(MOCK_TAG.slug) }) }) diff --git a/src/components/TagDigest/Sidebar/index.tsx b/src/components/TagDigest/Sidebar/index.tsx index db1803c63e..4423f7b21e 100644 --- a/src/components/TagDigest/Sidebar/index.tsx +++ b/src/components/TagDigest/Sidebar/index.tsx @@ -50,10 +50,7 @@ const Sidebar = ({ tag, ...cardProps }: TagDigestSidebarProps) => { testId={TEST_ID.DIGEST_TAG_SIDEBAR} >
    -
    +
    Date: Tue, 19 Nov 2024 16:03:20 +0700 Subject: [PATCH 26/69] fix(tag): fix tests --- src/common/utils/url.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utils/url.ts b/src/common/utils/url.ts index 7b21c4c012..39927a9206 100644 --- a/src/common/utils/url.ts +++ b/src/common/utils/url.ts @@ -48,7 +48,7 @@ const changeExt = ({ key, ext }: { key: string; ext?: 'webp' }) => { } export const toSizedImageURL = ({ - url, + url = '', width, height, ext, From e025a73d21e83b382e41fed04f669355859a1563 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:52:47 +0700 Subject: [PATCH 27/69] fix(campaign): show featured label for stage feeds --- .../ArticleFeeds/MainFeed/index.tsx | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx b/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx index 14d1cb9802..148a6de4f2 100644 --- a/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx +++ b/src/views/CampaignDetail/ArticleFeeds/MainFeed/index.tsx @@ -65,6 +65,17 @@ const getArticleStageName = ( ] } +const FeaturedLabel = () => ( + } + spacing={2} + color="freeWriteGreenLabel" + size={12} + > + + +) + const MainFeed = ({ feedType, camapign }: MainFeedProps) => { const viewer = useContext(ViewerContext) const { lang } = useContext(LanguageContext) @@ -212,8 +223,8 @@ const MainFeed = ({ feedType, camapign }: MainFeedProps) => { + <> + {(isAll || isFeatured) && ( { > {getArticleStageName(node, lang)} - - {isAll && featured && ( - - } - spacing={2} - color="freeWriteGreenLabel" - size={12} - > - - - )} - - ) + )} + {!isFeatured && featured && } + } onClick={() => { analytics.trackEvent('click_feed', { From 6286b52c732c264f18383d37685c1db26e46bc96 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:57:27 +0800 Subject: [PATCH 28/69] feat(TagDetail): add tag recommended authors --- lang/default.json | 4 + lang/en.json | 4 + lang/zh-Hans.json | 4 + lang/zh-Hant.json | 4 + src/common/utils/analytics.ts | 1 + src/views/TagDetail/RecommendedAuthors/gql.ts | 24 ++++++ .../TagDetail/RecommendedAuthors/index.tsx | 85 +++++++++++++++++++ .../RecommendedAuthors/styles.module.css | 29 +++++++ src/views/TagDetail/index.tsx | 10 ++- 9 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/views/TagDetail/RecommendedAuthors/gql.ts create mode 100644 src/views/TagDetail/RecommendedAuthors/index.tsx create mode 100644 src/views/TagDetail/RecommendedAuthors/styles.module.css diff --git a/lang/default.json b/lang/default.json index a244548115..c9a6ce6788 100644 --- a/lang/default.json +++ b/lang/default.json @@ -844,6 +844,10 @@ "defaultMessage": "upadted {date}", "description": "src/components/CollectionDigest/Feed/index.tsx" }, + "IUS82d": { + "defaultMessage": "Tag active authors", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "C9jbHn": { "defaultMessage": "Number of claps", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" diff --git a/lang/en.json b/lang/en.json index a7d7ba58bb..22d28f0367 100644 --- a/lang/en.json +++ b/lang/en.json @@ -844,6 +844,10 @@ "defaultMessage": "Upadted {date}", "description": "src/components/CollectionDigest/Feed/index.tsx" }, + "IUS82d": { + "defaultMessage": "Recommended Authors", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "C9jbHn": { "defaultMessage": "Number of claps", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 874fbfe04d..52db037f92 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -844,6 +844,10 @@ "defaultMessage": "{date}更新", "description": "src/components/CollectionDigest/Feed/index.tsx" }, + "IUS82d": { + "defaultMessage": "标签活跃作者", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "C9jbHn": { "defaultMessage": "拍手数量", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 2789029c75..d318929146 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -844,6 +844,10 @@ "defaultMessage": "{date}更新", "description": "src/components/CollectionDigest/Feed/index.tsx" }, + "IUS82d": { + "defaultMessage": "標籤活躍作者", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "C9jbHn": { "defaultMessage": "拍手數量", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" diff --git a/src/common/utils/analytics.ts b/src/common/utils/analytics.ts index 74c59c2a37..bb4bfc4eb0 100644 --- a/src/common/utils/analytics.ts +++ b/src/common/utils/analytics.ts @@ -340,6 +340,7 @@ type UserFeedType = | 'tag_detail_latest' | 'tag_detail_selected' | 'tag_detail_community' + | 'tag_detail_recommended_authors' | 'transaction' type TagFeedType = diff --git a/src/views/TagDetail/RecommendedAuthors/gql.ts b/src/views/TagDetail/RecommendedAuthors/gql.ts new file mode 100644 index 0000000000..f214b902c5 --- /dev/null +++ b/src/views/TagDetail/RecommendedAuthors/gql.ts @@ -0,0 +1,24 @@ +import gql from 'graphql-tag' + +import { UserDigest } from '~/components' + +export const RECOMMENDED_AUTHORS = gql` + query TagDetailRecommendedAuthors($id: ID!) { + node(input: { id: $id }) { + ... on Tag { + id + recommendedAuthors(input: { first: 5 }) { + edges { + cursor + node { + ...UserDigestRichUserPublic + ...UserDigestRichUserPrivate + } + } + } + } + } + } + ${UserDigest.Rich.fragments.user.public} + ${UserDigest.Rich.fragments.user.private} +` diff --git a/src/views/TagDetail/RecommendedAuthors/index.tsx b/src/views/TagDetail/RecommendedAuthors/index.tsx new file mode 100644 index 0000000000..ecd430d9f5 --- /dev/null +++ b/src/views/TagDetail/RecommendedAuthors/index.tsx @@ -0,0 +1,85 @@ +import classNames from 'classnames' +import _chunk from 'lodash/chunk' +import _get from 'lodash/get' +import _random from 'lodash/random' +import { FormattedMessage } from 'react-intl' + +import { analytics } from '~/common/utils' +import { List, usePublicQuery, UserDigest } from '~/components' +import { TagDetailRecommendedAuthorsQuery } from '~/gql/graphql' + +import { RECOMMENDED_AUTHORS } from './gql' +import styles from './styles.module.css' + +interface RecommendedAuthorsProps { + tagId: string + inSidebar?: boolean +} + +const RecommendedAuthorsHeader = () => { + return ( +
    + +
    + ) +} + +const RecommendedAuthors: React.FC = ({ + tagId, + inSidebar, +}) => { + const { data } = usePublicQuery( + RECOMMENDED_AUTHORS, + { + variables: { id: tagId }, + } + ) + + const { edges } = + (data?.node?.__typename === 'Tag' && data.node.recommendedAuthors) || {} + + const trackRecommendedAuthors = (i: number, id: string) => () => + analytics.trackEvent('click_feed', { + type: 'tag_detail_recommended_authors', + contentType: 'user', + location: i, + id, + }) + + if (!edges || edges.length <= 0) { + return null + } + + const recommendedAuthorsClasses = classNames({ + [styles.recommendedAuthors]: true, + [styles.inSidebar]: inSidebar, + }) + + return ( +
    + +
    + + {edges.map(({ node, cursor }, i) => ( + + trackRecommendedAuthors(i, node.id)} + hasFollow={false} + hasState={false} + /> + + ))} + +
    +
    + ) +} + +export default RecommendedAuthors diff --git a/src/views/TagDetail/RecommendedAuthors/styles.module.css b/src/views/TagDetail/RecommendedAuthors/styles.module.css new file mode 100644 index 0000000000..705672e91e --- /dev/null +++ b/src/views/TagDetail/RecommendedAuthors/styles.module.css @@ -0,0 +1,29 @@ +.recommendedAuthors { + padding-bottom: var(--sp24); + margin-top: var(--sp24); + border-bottom: 1px dashed var(--color-grey-light); +} + +.inSidebar { + padding-bottom: 0; + margin-top: 0; + border-bottom: none; +} + +.header { + margin-bottom: var(--sp18); + font-size: var(--text14); + font-weight: var(--font-medium); + line-height: 1.375rem; + color: var(--color-black); + + @media (--sm-up) { + margin-bottom: var(--sp20); + } +} + +.users { + & :global(.list-item + .list-item) { + margin-top: var(--sp20); + } +} diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index f04e4c8a5d..caa2d06ec5 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -34,6 +34,7 @@ import { TAG_DETAIL_PRIVATE, TAG_DETAIL_PUBLIC, } from './gql' +import RecommendedAuthors from './RecommendedAuthors' import RelatedTags from './RelatedTags' import styles from './styles.module.css' @@ -89,7 +90,14 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { * Render */ return ( - }> + + + + + } + > Date: Wed, 20 Nov 2024 14:59:06 +0800 Subject: [PATCH 29/69] fix(lang): format --- lang/default.json | 8 ++++---- lang/en.json | 8 ++++---- lang/zh-Hans.json | 8 ++++---- lang/zh-Hant.json | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lang/default.json b/lang/default.json index c9a6ce6788..b85ce210dc 100644 --- a/lang/default.json +++ b/lang/default.json @@ -844,10 +844,6 @@ "defaultMessage": "upadted {date}", "description": "src/components/CollectionDigest/Feed/index.tsx" }, - "IUS82d": { - "defaultMessage": "Tag active authors", - "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" - }, "C9jbHn": { "defaultMessage": "Number of claps", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1210,6 +1206,10 @@ "ISly67": { "defaultMessage": "Agree" }, + "IUS82d": { + "defaultMessage": "Tag active authors", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "IXycMo": { "defaultMessage": "Resend" }, diff --git a/lang/en.json b/lang/en.json index 22d28f0367..d6c53ab3b6 100644 --- a/lang/en.json +++ b/lang/en.json @@ -844,10 +844,6 @@ "defaultMessage": "Upadted {date}", "description": "src/components/CollectionDigest/Feed/index.tsx" }, - "IUS82d": { - "defaultMessage": "Recommended Authors", - "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" - }, "C9jbHn": { "defaultMessage": "Number of claps", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1210,6 +1206,10 @@ "ISly67": { "defaultMessage": "Agree" }, + "IUS82d": { + "defaultMessage": "Recommended Authors", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "IXycMo": { "defaultMessage": "Resend" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 52db037f92..72014d8144 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -844,10 +844,6 @@ "defaultMessage": "{date}更新", "description": "src/components/CollectionDigest/Feed/index.tsx" }, - "IUS82d": { - "defaultMessage": "标签活跃作者", - "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" - }, "C9jbHn": { "defaultMessage": "拍手数量", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1210,6 +1206,10 @@ "ISly67": { "defaultMessage": "同意" }, + "IUS82d": { + "defaultMessage": "标签活跃作者", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "IXycMo": { "defaultMessage": "重新发送" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index d318929146..5a9b2e57b6 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -844,10 +844,6 @@ "defaultMessage": "{date}更新", "description": "src/components/CollectionDigest/Feed/index.tsx" }, - "IUS82d": { - "defaultMessage": "標籤活躍作者", - "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" - }, "C9jbHn": { "defaultMessage": "拍手數量", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1210,6 +1206,10 @@ "ISly67": { "defaultMessage": "同意" }, + "IUS82d": { + "defaultMessage": "標籤活躍作者", + "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" + }, "IXycMo": { "defaultMessage": "重新發送" }, From f73fa149b44a88274d325488ed33485cf58a554a Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:14:33 +0800 Subject: [PATCH 30/69] feat(TagDetail): add recommended author in article feed --- src/common/styles/variables/spacing.css | 1 + src/views/TagDetail/Articles/index.tsx | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/common/styles/variables/spacing.css b/src/common/styles/variables/spacing.css index 4db77aa7c0..0c7f191178 100644 --- a/src/common/styles/variables/spacing.css +++ b/src/common/styles/variables/spacing.css @@ -9,6 +9,7 @@ --sp12: 0.75rem; /* 12px */ --sp14: 0.875rem; /* 14px */ --sp16: 1rem; /* 16px */ + --sp18: 1.125rem; /* 18px */ --sp20: 1.25rem; /* 20px */ --sp24: 1.5rem; /* 24px */ --sp32: 2rem; /* 32px */ diff --git a/src/views/TagDetail/Articles/index.tsx b/src/views/TagDetail/Articles/index.tsx index a6a9009591..0408e955c9 100644 --- a/src/views/TagDetail/Articles/index.tsx +++ b/src/views/TagDetail/Articles/index.tsx @@ -23,6 +23,7 @@ import { } from '~/components/GQL/queries/tagArticles' import { TagArticlesPublicQuery, TagFragmentFragment } from '~/gql/graphql' +import RecommendedAuthors from '../RecommendedAuthors' import RelatedTags from '../RelatedTags' interface TagArticlesProps { @@ -196,7 +197,13 @@ const TagDetailArticles = ({ tag, feedType }: TagArticlesProps) => { /> - {edges.length >= 4 && i === 3 && ( + {edges.length >= 2 && i === 0 && ( + + + + )} + + {edges.length >= 2 && i === 1 && ( @@ -205,8 +212,9 @@ const TagDetailArticles = ({ tag, feedType }: TagArticlesProps) => { ))} - {edges.length < 4 && ( + {edges.length < 2 && ( + )} From a9f07cecdd060908a5095a94c3889f616d64d8d7 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:34:26 +0800 Subject: [PATCH 31/69] feat(Bookmark): revise copy --- lang/default.json | 14 ++++++-------- lang/en.json | 14 ++++++-------- lang/zh-Hans.json | 14 ++++++-------- lang/zh-Hant.json | 14 ++++++-------- src/components/Buttons/Bookmark/Subscribe.tsx | 8 +------- src/components/Buttons/Bookmark/Unsubscribe.tsx | 6 +----- 6 files changed, 26 insertions(+), 44 deletions(-) diff --git a/lang/default.json b/lang/default.json index b85ce210dc..02c7c98d9a 100644 --- a/lang/default.json +++ b/lang/default.json @@ -626,6 +626,9 @@ "8YgVvt": { "defaultMessage": "Like collection" }, + "8ZyDQJ": { + "defaultMessage": "Bookmark removed" + }, "8cv9D4": { "defaultMessage": "Next Step" }, @@ -2610,6 +2613,9 @@ "defaultMessage": "broadcast in {circlename}", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, + "k0fraU": { + "defaultMessage": "Bookmarked" + }, "k2veDA": { "defaultMessage": "Write" }, @@ -2644,10 +2650,6 @@ "defaultMessage": "Liker ID", "description": "src/views/Me/Settings/Misc/LikerID.tsx" }, - "kSt4il": { - "defaultMessage": "Bookmark removed", - "description": "src/components/Buttons/Bookmark/Unsubscribe.tsx" - }, "kc79d3": { "defaultMessage": "Topics" }, @@ -2926,10 +2928,6 @@ "defaultMessage": "commented in your moment", "description": "src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx" }, - "qE8ew4": { - "defaultMessage": "Bookmarked", - "description": "src/components/Buttons/Bookmark/Subscribe.tsx" - }, "qNuRmA": { "defaultMessage": "Send login code", "description": "src/components/Forms/EmailLoginForm/Buttons.tsx" diff --git a/lang/en.json b/lang/en.json index d6c53ab3b6..d0bd82c3cd 100644 --- a/lang/en.json +++ b/lang/en.json @@ -626,6 +626,9 @@ "8YgVvt": { "defaultMessage": "Like collection" }, + "8ZyDQJ": { + "defaultMessage": "Bookmark removed" + }, "8cv9D4": { "defaultMessage": "Next Step" }, @@ -2610,6 +2613,9 @@ "defaultMessage": "broadcast in {circlename}", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, + "k0fraU": { + "defaultMessage": "Bookmarked" + }, "k2veDA": { "defaultMessage": "Write" }, @@ -2644,10 +2650,6 @@ "defaultMessage": "Liker ID", "description": "src/views/Me/Settings/Misc/LikerID.tsx" }, - "kSt4il": { - "defaultMessage": "Bookmark removed", - "description": "src/components/Buttons/Bookmark/Unsubscribe.tsx" - }, "kc79d3": { "defaultMessage": "Topics" }, @@ -2926,10 +2928,6 @@ "defaultMessage": "commented in your moment", "description": "src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx" }, - "qE8ew4": { - "defaultMessage": "Bookmarked", - "description": "src/components/Buttons/Bookmark/Subscribe.tsx" - }, "qNuRmA": { "defaultMessage": "Send login code", "description": "src/components/Forms/EmailLoginForm/Buttons.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 72014d8144..1c8a3ded35 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -626,6 +626,9 @@ "8YgVvt": { "defaultMessage": "喜欢选集" }, + "8ZyDQJ": { + "defaultMessage": "收藏已取消" + }, "8cv9D4": { "defaultMessage": "下一步" }, @@ -2610,6 +2613,9 @@ "defaultMessage": "在 {circlename} 发布广播", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, + "k0fraU": { + "defaultMessage": "收藏成功" + }, "k2veDA": { "defaultMessage": "创作" }, @@ -2644,10 +2650,6 @@ "defaultMessage": "Liker ID", "description": "src/views/Me/Settings/Misc/LikerID.tsx" }, - "kSt4il": { - "defaultMessage": "收藏已取消", - "description": "src/components/Buttons/Bookmark/Unsubscribe.tsx" - }, "kc79d3": { "defaultMessage": "找你想看的" }, @@ -2926,10 +2928,6 @@ "defaultMessage": "在动态中留言", "description": "src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx" }, - "qE8ew4": { - "defaultMessage": "收藏成功", - "description": "src/components/Buttons/Bookmark/Subscribe.tsx" - }, "qNuRmA": { "defaultMessage": "发送临时密码", "description": "src/components/Forms/EmailLoginForm/Buttons.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 5a9b2e57b6..93e103910d 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -626,6 +626,9 @@ "8YgVvt": { "defaultMessage": "喜歡選集" }, + "8ZyDQJ": { + "defaultMessage": "收藏已取消" + }, "8cv9D4": { "defaultMessage": "下一步" }, @@ -2610,6 +2613,9 @@ "defaultMessage": "在 {circlename} 發布廣播", "description": "src/components/Notice/CommentNotice/CircleNewBroadcastNotice.tsx" }, + "k0fraU": { + "defaultMessage": "收藏成功" + }, "k2veDA": { "defaultMessage": "創作" }, @@ -2644,10 +2650,6 @@ "defaultMessage": "Liker ID", "description": "src/views/Me/Settings/Misc/LikerID.tsx" }, - "kSt4il": { - "defaultMessage": "收藏已取消", - "description": "src/components/Buttons/Bookmark/Unsubscribe.tsx" - }, "kc79d3": { "defaultMessage": "找你想看的" }, @@ -2926,10 +2928,6 @@ "defaultMessage": "在動態中留言", "description": "src/components/Notice/CommentNotice/MomentNewCommentNotice.tsx" }, - "qE8ew4": { - "defaultMessage": "收藏成功", - "description": "src/components/Buttons/Bookmark/Subscribe.tsx" - }, "qNuRmA": { "defaultMessage": "發送臨時密碼", "description": "src/components/Forms/EmailLoginForm/Buttons.tsx" diff --git a/src/components/Buttons/Bookmark/Subscribe.tsx b/src/components/Buttons/Bookmark/Subscribe.tsx index c50b67f6de..1ef0494750 100644 --- a/src/components/Buttons/Bookmark/Subscribe.tsx +++ b/src/components/Buttons/Bookmark/Subscribe.tsx @@ -71,13 +71,7 @@ const Subscribe = ({ await subscribe() toast.success({ - message: ( - - ), + message: , }) } diff --git a/src/components/Buttons/Bookmark/Unsubscribe.tsx b/src/components/Buttons/Bookmark/Unsubscribe.tsx index 46ad5bd880..1acbf9a5d4 100644 --- a/src/components/Buttons/Bookmark/Unsubscribe.tsx +++ b/src/components/Buttons/Bookmark/Unsubscribe.tsx @@ -57,11 +57,7 @@ const Unsubscribe = ({ toast.success({ message: ( - + ), }) } From 21842360e5131a0629dbaa46b3b5a0e49b0f6495 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:36:48 +0800 Subject: [PATCH 32/69] feat(TagDetail): add toast after follow/unfollow --- .../TagDetail/Buttons/BookmarkButton/Bookmark.tsx | 13 ++++++++++--- .../TagDetail/Buttons/BookmarkButton/Unbookmark.tsx | 13 +++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx index 5fbacf21d3..2f131bde8d 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx @@ -7,7 +7,7 @@ import { OPEN_UNIVERSAL_AUTH_DIALOG, UNIVERSAL_AUTH_TRIGGER, } from '~/common/enums' -import { Button, Icon, useMutation, ViewerContext } from '~/components' +import { Button, Icon, toast, useMutation, ViewerContext } from '~/components' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { BookmarkButtonTagPrivateFragment, @@ -35,7 +35,7 @@ const Bookmark = ({ tag }: BookmarkProps) => { : undefined, }) - const onClick = () => { + const onClick = async () => { if (!viewer.isAuthed) { window.dispatchEvent( new CustomEvent(OPEN_UNIVERSAL_AUTH_DIALOG, { @@ -45,7 +45,14 @@ const Bookmark = ({ tag }: BookmarkProps) => { return } - follow() + await follow() + + toast.success({ + message: intl.formatMessage({ + defaultMessage: 'Bookmarked', + id: 'k0fraU', + }), + }) } return ( diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx index a170834ce0..eaac6eec20 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx @@ -2,7 +2,7 @@ import _isNil from 'lodash/isNil' import { useIntl } from 'react-intl' import { ReactComponent as IconSave2 } from '@/public/static/icons/24px/save2.svg' -import { Button, Icon, useMutation } from '~/components' +import { Button, Icon, toast, useMutation } from '~/components' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { BookmarkButtonTagPrivateFragment, @@ -31,6 +31,15 @@ const Unbookmark = ({ tag }: UnbookmarkTagProps) => { : undefined, } ) + const onClick = async () => { + await unfollow() + toast.success({ + message: intl.formatMessage({ + defaultMessage: 'Bookmark removed', + id: '8ZyDQJ', + }), + }) + } return ( From ebe175d86994cfa91e842215a66e02834301c070 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:42:46 +0800 Subject: [PATCH 33/69] feat(EmptyTagArticles): update icon --- src/components/Empty/EmptyTagArticles.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Empty/EmptyTagArticles.tsx b/src/components/Empty/EmptyTagArticles.tsx index f2e7274d6b..3c726d332f 100644 --- a/src/components/Empty/EmptyTagArticles.tsx +++ b/src/components/Empty/EmptyTagArticles.tsx @@ -1,9 +1,9 @@ -import { ReactComponent as IconWarn } from '@/public/static/icons/24px/warn.svg' +import { ReactComponent as IconEmptyFile } from '@/public/static/icons/empty-file.svg' import { Empty, Icon, Translate } from '~/components' export const EmptyTagArticles = () => ( } + icon={} description={ } From 79fd322f2674be31c186ab3e062f6397227af3cf Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:22:03 +0800 Subject: [PATCH 34/69] fix(TagDetail): update variable name --- src/common/enums/events.ts | 1 + .../Buttons/BookmarkButton/Bookmark.tsx | 33 ++++++++++--------- .../Buttons/BookmarkButton/Unbookmark.tsx | 4 +-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/common/enums/events.ts b/src/common/enums/events.ts index 7dfcf5783b..f40039c0a2 100644 --- a/src/common/enums/events.ts +++ b/src/common/enums/events.ts @@ -55,6 +55,7 @@ export const SUPPORT_SUCCESS_ANIMATION = 'supportSuccessAnimation' export enum UNIVERSAL_AUTH_TRIGGER { appreciation = 'appreciation', bookmark = 'bookmark', + bookmarkTag = 'bookmarkTag', circlePrice = 'circlePrice', circleSubscription = 'circleSubscription', collectArticle = 'collectArticle', diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx index 2f131bde8d..27fec490d0 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx @@ -21,31 +21,34 @@ interface BookmarkProps { const Bookmark = ({ tag }: BookmarkProps) => { const viewer = useContext(ViewerContext) const intl = useIntl() - const [follow] = useMutation(TOGGLE_BOOKMARK_TAG, { - variables: { id: tag.id, enabled: true }, - optimisticResponse: - !_isNil(tag.id) && !_isNil(tag.isFollower) - ? { - toggleBookmarkTag: { - id: tag.id, - isFollower: true, - __typename: 'Tag', - }, - } - : undefined, - }) + const [bookmark] = useMutation( + TOGGLE_BOOKMARK_TAG, + { + variables: { id: tag.id, enabled: true }, + optimisticResponse: + !_isNil(tag.id) && !_isNil(tag.isFollower) + ? { + toggleBookmarkTag: { + id: tag.id, + isFollower: true, + __typename: 'Tag', + }, + } + : undefined, + } + ) const onClick = async () => { if (!viewer.isAuthed) { window.dispatchEvent( new CustomEvent(OPEN_UNIVERSAL_AUTH_DIALOG, { - detail: { trigger: UNIVERSAL_AUTH_TRIGGER.followTag }, + detail: { trigger: UNIVERSAL_AUTH_TRIGGER.bookmarkTag }, }) ) return } - await follow() + await bookmark() toast.success({ message: intl.formatMessage({ diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx index eaac6eec20..3d29adc871 100644 --- a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx +++ b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx @@ -15,7 +15,7 @@ interface UnbookmarkTagProps { const Unbookmark = ({ tag }: UnbookmarkTagProps) => { const intl = useIntl() - const [unfollow] = useMutation( + const [unbookmark] = useMutation( TOGGLE_BOOKMARK_TAG, { variables: { id: tag.id, enabled: false }, @@ -32,7 +32,7 @@ const Unbookmark = ({ tag }: UnbookmarkTagProps) => { } ) const onClick = async () => { - await unfollow() + await unbookmark() toast.success({ message: intl.formatMessage({ defaultMessage: 'Bookmark removed', From 885c6cb567e20569ccae1674e2d151a23a9d1177 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:28:07 +0800 Subject: [PATCH 35/69] fix(TagDetail): remove random filter --- src/views/TagDetail/RelatedTags/gql.ts | 4 ++-- src/views/TagDetail/RelatedTags/index.tsx | 13 ++----------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/views/TagDetail/RelatedTags/gql.ts b/src/views/TagDetail/RelatedTags/gql.ts index 4c40aaa88a..d5cf1cd5d9 100644 --- a/src/views/TagDetail/RelatedTags/gql.ts +++ b/src/views/TagDetail/RelatedTags/gql.ts @@ -3,11 +3,11 @@ import gql from 'graphql-tag' import { TagDigest } from '~/components' export const RELATED_TAGS = gql` - query TagDetailRecommended($id: ID!, $random: random_Int_min_0_max_49) { + query TagDetailRecommended($id: ID!) { node(input: { id: $id }) { ... on Tag { id - recommended(input: { first: 10, filter: { random: $random } }) { + recommended(input: { first: 5 }) { edges { cursor node { diff --git a/src/views/TagDetail/RelatedTags/index.tsx b/src/views/TagDetail/RelatedTags/index.tsx index be3858032a..f9ffb15a41 100644 --- a/src/views/TagDetail/RelatedTags/index.tsx +++ b/src/views/TagDetail/RelatedTags/index.tsx @@ -1,4 +1,3 @@ -import { useQuery } from '@apollo/react-hooks' import classNames from 'classnames' import _chunk from 'lodash/chunk' import _get from 'lodash/get' @@ -7,8 +6,7 @@ import { FormattedMessage } from 'react-intl' import { analytics } from '~/common/utils' import { ArticleTag, usePublicQuery } from '~/components' -import FETCH_RECORD from '~/components/GQL/queries/lastFetchRandom' -import { LastFetchRandomQuery, TagDetailRecommendedQuery } from '~/gql/graphql' +import { TagDetailRecommendedQuery } from '~/gql/graphql' import { RELATED_TAGS } from './gql' import styles from './styles.module.css' @@ -31,15 +29,8 @@ const RelatedTagsHeader = () => { } const RelatedTags: React.FC = ({ tagId, inSidebar }) => { - const { data: lastFetchRandom } = useQuery( - FETCH_RECORD, - { variables: { id: 'local' } } - ) - - const lastRandom = lastFetchRandom?.lastFetchRandom.feedTags - const { data } = usePublicQuery(RELATED_TAGS, { - variables: { id: tagId, random: lastRandom || 0 }, + variables: { id: tagId }, }) const { edges } = From 3eb04359f2cf7fb76c2773574bfba20aa2af62e0 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:34:52 +0800 Subject: [PATCH 36/69] fix(TagDetail): remove private fields in gql --- src/views/TagDetail/RecommendedAuthors/gql.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/views/TagDetail/RecommendedAuthors/gql.ts b/src/views/TagDetail/RecommendedAuthors/gql.ts index f214b902c5..5bf0969989 100644 --- a/src/views/TagDetail/RecommendedAuthors/gql.ts +++ b/src/views/TagDetail/RecommendedAuthors/gql.ts @@ -12,7 +12,6 @@ export const RECOMMENDED_AUTHORS = gql` cursor node { ...UserDigestRichUserPublic - ...UserDigestRichUserPrivate } } } @@ -20,5 +19,4 @@ export const RECOMMENDED_AUTHORS = gql` } } ${UserDigest.Rich.fragments.user.public} - ${UserDigest.Rich.fragments.user.private} ` From 73193cde79d393211bf3da239ef77cffd8f28bee Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:26:18 +0800 Subject: [PATCH 37/69] fix(TagDetail): default tab set to latest & remove unused tab option --- src/views/TagDetail/index.tsx | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index caa2d06ec5..c67140cfa0 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -38,7 +38,7 @@ import RecommendedAuthors from './RecommendedAuthors' import RelatedTags from './RelatedTags' import styles from './styles.module.css' -const validTagFeedTypes = ['hottest', 'latest', 'selected', 'creators'] as const +const validTagFeedTypes = ['hottest', 'latest'] as const type TagFeedType = (typeof validTagFeedTypes)[number] const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { @@ -48,11 +48,8 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { // feed type const { getQuery, setQuery } = useRoute() const qsType = getQuery('type') as TagFeedType - const hasSelectedFeed = (tag?.selectedArticles.totalCount || 0) > 0 - const [feedType, setFeedType] = useState( - hasSelectedFeed && qsType === 'selected' ? 'selected' : qsType || 'hottest' - ) + const [feedType, setFeedType] = useState(qsType || 'latest') const changeFeed = (newType: TagFeedType) => { setQuery('type', newType) @@ -60,11 +57,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { } useEffect(() => { - setFeedType( - hasSelectedFeed && qsType === 'selected' - ? 'selected' - : qsType || 'hottest' - ) + setFeedType(qsType || 'latest') }, [qsType]) const isHottest = feedType === 'hottest' From 3e1044534709fd3437f3e137027b6a7c81a0629a Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:42:14 +0800 Subject: [PATCH 38/69] feat(tag): hide feed tabs when tag has no articles - Add conditional rendering for feed type tabs based on tag.numArticles - Improve UI by preventing empty tab display --- src/views/TagDetail/index.tsx | 45 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index c67140cfa0..a966f9eb80 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -62,6 +62,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const isHottest = feedType === 'hottest' const isLatest = feedType === 'latest' + const hasArticles = tag.numArticles > 0 useEffect(() => { // backward compatible with `/tags/:globalId:` @@ -127,27 +128,29 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => {
    -
    - - changeFeed('latest')} - title={intl.formatMessage({ - defaultMessage: 'Latest', - id: 'adThp5', - })} - /> - - changeFeed('hottest')} - title={intl.formatMessage({ - defaultMessage: 'Trending', - id: 'll/ufR', - })} - /> - -
    + {hasArticles && ( +
    + + changeFeed('latest')} + title={intl.formatMessage({ + defaultMessage: 'Latest', + id: 'adThp5', + })} + /> + + changeFeed('hottest')} + title={intl.formatMessage({ + defaultMessage: 'Trending', + id: 'll/ufR', + })} + /> + +
    + )} From 1a4162e45a1f8c3f8fc58b3bbab443c0e3bf18f7 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:56:39 +0800 Subject: [PATCH 39/69] feat(UserProfile): Remove tag following functionality from Following Dialog --- lang/default.json | 3 - lang/en.json | 3 - lang/zh-Hans.json | 3 - lang/zh-Hant.json | 3 - .../FollowingDialog/Content/index.tsx | 2 - .../FollowingDialog/FeedType/index.tsx | 7 - .../FollowingDialog/TagsFeed/gql.ts | 48 ------- .../FollowingDialog/TagsFeed/index.tsx | 127 ------------------ 8 files changed, 196 deletions(-) delete mode 100644 src/views/User/UserProfile/FollowingDialog/TagsFeed/gql.ts delete mode 100644 src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx diff --git a/lang/default.json b/lang/default.json index 02c7c98d9a..97d5cf30f2 100644 --- a/lang/default.json +++ b/lang/default.json @@ -2127,9 +2127,6 @@ "ZZ9zIR": { "defaultMessage": "Downvote" }, - "Zakh0i": { - "defaultMessage": "Not following any tag" - }, "ZjDH42": { "defaultMessage": "About Us" }, diff --git a/lang/en.json b/lang/en.json index d0bd82c3cd..46a730730f 100644 --- a/lang/en.json +++ b/lang/en.json @@ -2127,9 +2127,6 @@ "ZZ9zIR": { "defaultMessage": "Downvote" }, - "Zakh0i": { - "defaultMessage": "Not following any tag" - }, "ZjDH42": { "defaultMessage": "About Us" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 1c8a3ded35..e7d00c7a75 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -2127,9 +2127,6 @@ "ZZ9zIR": { "defaultMessage": "点踩" }, - "Zakh0i": { - "defaultMessage": "还没有关注任何标签" - }, "ZjDH42": { "defaultMessage": "关于我们" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 93e103910d..7ead551a8e 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -2127,9 +2127,6 @@ "ZZ9zIR": { "defaultMessage": "點踩" }, - "Zakh0i": { - "defaultMessage": "還沒有追蹤任何標籤" - }, "ZjDH42": { "defaultMessage": "關於我們" }, diff --git a/src/views/User/UserProfile/FollowingDialog/Content/index.tsx b/src/views/User/UserProfile/FollowingDialog/Content/index.tsx index 8441b74c43..d0cb22c13d 100644 --- a/src/views/User/UserProfile/FollowingDialog/Content/index.tsx +++ b/src/views/User/UserProfile/FollowingDialog/Content/index.tsx @@ -4,7 +4,6 @@ import { Dialog, Spacer } from '~/components' import CirclesFeed from '../CirclesFeed' import FeedType, { FollowingFeedType } from '../FeedType' -import TagsFeed from '../TagsFeed' import UsersFeed from '../UsersFeed' const FollowingDialogContent = () => { @@ -15,7 +14,6 @@ const FollowingDialogContent = () => { {feedType === 'circle' && } - {feedType === 'tag' && } {feedType === 'user' && } ) diff --git a/src/views/User/UserProfile/FollowingDialog/FeedType/index.tsx b/src/views/User/UserProfile/FollowingDialog/FeedType/index.tsx index 5b83b21132..039fa04811 100644 --- a/src/views/User/UserProfile/FollowingDialog/FeedType/index.tsx +++ b/src/views/User/UserProfile/FollowingDialog/FeedType/index.tsx @@ -2,8 +2,6 @@ import { Tabs, Translate } from '~/components' export type FollowingFeedType = 'user' | 'circle' | 'tag' -import { FormattedMessage } from 'react-intl' - import styles from './styles.module.css' interface FeedTypeProps { @@ -13,7 +11,6 @@ interface FeedTypeProps { const FeedType = ({ type, setFeedType }: FeedTypeProps) => { const isCircle = type === 'circle' - const isTag = type === 'tag' const isUser = type === 'user' return ( @@ -26,10 +23,6 @@ const FeedType = ({ type, setFeedType }: FeedTypeProps) => { setFeedType('circle')} selected={isCircle}> - - setFeedType('tag')} selected={isTag}> - -
    ) diff --git a/src/views/User/UserProfile/FollowingDialog/TagsFeed/gql.ts b/src/views/User/UserProfile/FollowingDialog/TagsFeed/gql.ts deleted file mode 100644 index ef5122e0b0..0000000000 --- a/src/views/User/UserProfile/FollowingDialog/TagsFeed/gql.ts +++ /dev/null @@ -1,48 +0,0 @@ -import gql from 'graphql-tag' - -import { TagDigest } from '~/components' - -export const USER_FOLLOWING_TAGS_PUBLIC = gql` - query UserFollowingTagsPublic($userName: String!, $after: String) { - user(input: { userName: $userName }) { - id - info { - profileCover - description - } - status { - state - } - following { - tags(input: { first: 20, after: $after }) { - pageInfo { - startCursor - endCursor - hasNextPage - } - edges { - cursor - node { - ...TagDigestRichTagPublic - ...TagDigestRichTagPrivate - } - } - } - } - } - } - ${TagDigest.Rich.fragments.tag.public} - ${TagDigest.Rich.fragments.tag.private} -` - -export const USER_FOLLOWING_TAGS_PRIVATE = gql` - query UserFollowingTagsPrivate($ids: [ID!]!) { - nodes(input: { ids: $ids }) { - id - ... on Tag { - ...TagDigestRichTagPrivate - } - } - } - ${TagDigest.Rich.fragments.tag.private} -` diff --git a/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx b/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx deleted file mode 100644 index fcebbeaafa..0000000000 --- a/src/views/User/UserProfile/FollowingDialog/TagsFeed/index.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { useContext, useEffect } from 'react' -import { FormattedMessage } from 'react-intl' - -import { analytics, mergeConnections } from '~/common/utils' -import { - EmptyWarning, - InfiniteScroll, - List, - QueryError, - SpinnerBlock, - TagDigest, - usePublicQuery, - useRoute, - ViewerContext, -} from '~/components' -import { UserFollowingTagsPublicQuery } from '~/gql/graphql' - -import { USER_FOLLOWING_TAGS_PRIVATE, USER_FOLLOWING_TAGS_PUBLIC } from './gql' - -const TagsFeed = () => { - const viewer = useContext(ViewerContext) - const { getQuery } = useRoute() - const userName = getQuery('name') - - /** - * Data Fetching - */ - // public data - const { data, loading, error, fetchMore, client } = - usePublicQuery(USER_FOLLOWING_TAGS_PUBLIC, { - variables: { userName }, - }) - - // pagination - const user = data?.user - const connectionPath = 'user.following.tags' - const { edges, pageInfo } = user?.following?.tags || {} - - // private data - const loadPrivate = (publicData?: UserFollowingTagsPublicQuery) => { - if (!viewer.isAuthed || !publicData || !user) { - return - } - - const publicEdges = publicData.user?.following?.tags.edges || [] - const publicIds = publicEdges.map(({ node }) => node.id) - client.query({ - query: USER_FOLLOWING_TAGS_PRIVATE, - fetchPolicy: 'network-only', - variables: { ids: publicIds }, - }) - } - - // fetch private data for first page - useEffect(() => { - loadPrivate(data) - }, [user?.id, viewer.id]) - - // load next page - const loadMore = async () => { - analytics.trackEvent('load_more', { - type: 'followee', - location: edges?.length || 0, - }) - const { data: newData } = await fetchMore({ - variables: { after: pageInfo?.endCursor }, - updateQuery: (previousResult, { fetchMoreResult }) => - mergeConnections({ - oldData: previousResult, - newData: fetchMoreResult, - path: connectionPath, - }), - }) - - loadPrivate(newData) - } - - /** - * Render - */ - if (loading) { - return - } - - if (error) { - return - } - - if ( - !user || - user?.status?.state === 'archived' || - !edges || - edges.length <= 0 || - !pageInfo - ) { - return ( - - } - /> - ) - } - - return ( - - - {edges.map(({ node, cursor }, i) => ( - - - - ))} - - - ) -} - -export default TagsFeed From 067470ab427e03b932abe72f2c16469ce741c6ba Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Thu, 21 Nov 2024 19:34:08 +0700 Subject: [PATCH 40/69] fix: correct copy of CollectionDigest --- lang/default.json | 8 ++++---- lang/en.json | 8 ++++---- lang/zh-Hans.json | 8 ++++---- lang/zh-Hant.json | 8 ++++---- src/components/CollectionDigest/Feed/index.tsx | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lang/default.json b/lang/default.json index 02c7c98d9a..fa014e869f 100644 --- a/lang/default.json +++ b/lang/default.json @@ -843,10 +843,6 @@ "defaultMessage": "Connected to {type}", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" }, - "C8GQaD": { - "defaultMessage": "upadted {date}", - "description": "src/components/CollectionDigest/Feed/index.tsx" - }, "C9jbHn": { "defaultMessage": "Number of claps", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1158,6 +1154,10 @@ "HbEL82": { "defaultMessage": "Comment has been deleted" }, + "HbwwAe": { + "defaultMessage": "Updated {date}", + "description": "src/components/CollectionDigest/Feed/index.tsx" + }, "HgY+72": { "defaultMessage": "Apply", "description": "src/views/CampaignDetail/Apply/Button/index.tsx" diff --git a/lang/en.json b/lang/en.json index d0bd82c3cd..22015f4e2e 100644 --- a/lang/en.json +++ b/lang/en.json @@ -843,10 +843,6 @@ "defaultMessage": "Connected to {type}", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" }, - "C8GQaD": { - "defaultMessage": "Upadted {date}", - "description": "src/components/CollectionDigest/Feed/index.tsx" - }, "C9jbHn": { "defaultMessage": "Number of claps", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1158,6 +1154,10 @@ "HbEL82": { "defaultMessage": "Comment has been deleted" }, + "HbwwAe": { + "defaultMessage": "Updated {date}", + "description": "src/components/CollectionDigest/Feed/index.tsx" + }, "HgY+72": { "defaultMessage": "Apply", "description": "src/views/CampaignDetail/Apply/Button/index.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 1c8a3ded35..21c3314ecf 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -843,10 +843,6 @@ "defaultMessage": "{type} 已绑定", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" }, - "C8GQaD": { - "defaultMessage": "{date}更新", - "description": "src/components/CollectionDigest/Feed/index.tsx" - }, "C9jbHn": { "defaultMessage": "拍手数量", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1158,6 +1154,10 @@ "HbEL82": { "defaultMessage": "评论已刪除" }, + "HbwwAe": { + "defaultMessage": "{date}更新", + "description": "src/components/CollectionDigest/Feed/index.tsx" + }, "HgY+72": { "defaultMessage": "报名参加", "description": "src/views/CampaignDetail/Apply/Button/index.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 93e103910d..1ebd973325 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -843,10 +843,6 @@ "defaultMessage": "{type} 已綁定", "description": "src/views/Me/Settings/Settings/Socials/index.tsx" }, - "C8GQaD": { - "defaultMessage": "{date}更新", - "description": "src/components/CollectionDigest/Feed/index.tsx" - }, "C9jbHn": { "defaultMessage": "拍手數量", "description": "src/components/ArticleDigest/Published/FooterActions/index.tsx" @@ -1158,6 +1154,10 @@ "HbEL82": { "defaultMessage": "評論已刪除" }, + "HbwwAe": { + "defaultMessage": "{date}更新", + "description": "src/components/CollectionDigest/Feed/index.tsx" + }, "HgY+72": { "defaultMessage": "報名參加", "description": "src/views/CampaignDetail/Apply/Button/index.tsx" diff --git a/src/components/CollectionDigest/Feed/index.tsx b/src/components/CollectionDigest/Feed/index.tsx index 5fae3445f3..d9ecb28f49 100644 --- a/src/components/CollectionDigest/Feed/index.tsx +++ b/src/components/CollectionDigest/Feed/index.tsx @@ -87,8 +87,8 @@ const BaseCollectionDigestFeed = ({ , From ab30d3a1f02d1bf0b108ea3313c62e4930ead53f Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:24:14 +0800 Subject: [PATCH 41/69] feat(Bookmarks): split bookmarks into articles and tags views --- lang/default.json | 4 + lang/en.json | 4 + lang/zh-Hans.json | 4 + lang/zh-Hant.json | 4 + src/common/enums/route.ts | 6 +- .../DrawerContent/MeMenu/index.tsx | 2 +- src/components/Layout/SideNav/MeMenu.tsx | 2 +- src/pages/me/bookmarks.tsx | 10 -- src/pages/me/bookmarks/articles.tsx | 10 ++ src/pages/me/bookmarks/index.tsx | 14 +++ src/pages/me/bookmarks/tags.tsx | 10 ++ .../{index.tsx => BookmarksArticles.tsx} | 20 +-- src/views/Me/Bookmarks/BookmarksTabs.tsx | 32 +++++ src/views/Me/Bookmarks/BookmarksTags.tsx | 117 ++++++++++++++++++ 14 files changed, 217 insertions(+), 22 deletions(-) delete mode 100644 src/pages/me/bookmarks.tsx create mode 100644 src/pages/me/bookmarks/articles.tsx create mode 100644 src/pages/me/bookmarks/index.tsx create mode 100644 src/pages/me/bookmarks/tags.tsx rename src/views/Me/Bookmarks/{index.tsx => BookmarksArticles.tsx} (83%) create mode 100644 src/views/Me/Bookmarks/BookmarksTabs.tsx create mode 100644 src/views/Me/Bookmarks/BookmarksTags.tsx diff --git a/lang/default.json b/lang/default.json index 02c7c98d9a..bb93e468ec 100644 --- a/lang/default.json +++ b/lang/default.json @@ -765,6 +765,10 @@ "AeVndq": { "defaultMessage": "mentioned you in a comment at {commentMoment}" }, + "Ajc5SE": { + "defaultMessage": "Articles", + "description": "src/views/Me/Bookmarks/Tabs.tsx" + }, "AlHYvk": { "defaultMessage": "{type} edited" }, diff --git a/lang/en.json b/lang/en.json index d0bd82c3cd..389336fe56 100644 --- a/lang/en.json +++ b/lang/en.json @@ -765,6 +765,10 @@ "AeVndq": { "defaultMessage": "mentioned you in a comment at {commentMoment}" }, + "Ajc5SE": { + "defaultMessage": "Articles", + "description": "src/views/Me/Bookmarks/Tabs.tsx" + }, "AlHYvk": { "defaultMessage": "{type} edited" }, diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 1c8a3ded35..cf26c12963 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -765,6 +765,10 @@ "AeVndq": { "defaultMessage": "在动态留言中提及了你 {commentMoment}" }, + "Ajc5SE": { + "defaultMessage": "Articles", + "description": "src/views/Me/Bookmarks/Tabs.tsx" + }, "AlHYvk": { "defaultMessage": "{type}已编辑" }, diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 93e103910d..628f6adad8 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -765,6 +765,10 @@ "AeVndq": { "defaultMessage": "在動態留言中提及了你 {commentMoment}" }, + "Ajc5SE": { + "defaultMessage": "Articles", + "description": "src/views/Me/Bookmarks/Tabs.tsx" + }, "AlHYvk": { "defaultMessage": "{type}已編輯" }, diff --git a/src/common/enums/route.ts b/src/common/enums/route.ts index 182f5951b2..7ab3eb77f5 100644 --- a/src/common/enums/route.ts +++ b/src/common/enums/route.ts @@ -40,7 +40,8 @@ type ROUTE_KEY = | 'ME_DRAFTS' | 'ME_PUBLISHED' | 'ME_ARCHIVED' - | 'ME_BOOKMARKS' + | 'ME_BOOKMARKS_ARTICLES' + | 'ME_BOOKMARKS_TAGS' | 'ME_HISTORY' | 'ME_HISTORY_COMMENTS' | 'ME_HISTORY_LIKES_SENT' @@ -146,7 +147,8 @@ export const ROUTES: { { key: 'ME_DRAFTS', pathname: '/me/drafts' }, { key: 'ME_PUBLISHED', pathname: '/me/published' }, { key: 'ME_ARCHIVED', pathname: '/me/archived' }, - { key: 'ME_BOOKMARKS', pathname: '/me/bookmarks' }, + { key: 'ME_BOOKMARKS_ARTICLES', pathname: '/me/bookmarks/articles' }, + { key: 'ME_BOOKMARKS_TAGS', pathname: '/me/bookmarks/tags' }, { key: 'ME_HISTORY', pathname: '/me/history' }, { key: 'ME_HISTORY_COMMENTS', pathname: '/me/history/comments' }, { key: 'ME_HISTORY_LIKES_SENT', pathname: '/me/history/likes/sent' }, diff --git a/src/components/Layout/Header/MeButton/SideDrawerNav/DrawerContent/MeMenu/index.tsx b/src/components/Layout/Header/MeButton/SideDrawerNav/DrawerContent/MeMenu/index.tsx index e11ae774b4..f4f2ac2c6a 100644 --- a/src/components/Layout/Header/MeButton/SideDrawerNav/DrawerContent/MeMenu/index.tsx +++ b/src/components/Layout/Header/MeButton/SideDrawerNav/DrawerContent/MeMenu/index.tsx @@ -61,7 +61,7 @@ const Top: React.FC = () => { {...menuItemProps} text={} icon={} - href={PATHS.ME_BOOKMARKS} + href={PATHS.ME_BOOKMARKS_ARTICLES} is="link" /> diff --git a/src/components/Layout/SideNav/MeMenu.tsx b/src/components/Layout/SideNav/MeMenu.tsx index 66907f2b16..f13390a273 100644 --- a/src/components/Layout/SideNav/MeMenu.tsx +++ b/src/components/Layout/SideNav/MeMenu.tsx @@ -73,7 +73,7 @@ const MeMenu: React.FC = () => { } icon={} - href={PATHS.ME_BOOKMARKS} + href={PATHS.ME_BOOKMARKS_ARTICLES} is="link" /> diff --git a/src/pages/me/bookmarks.tsx b/src/pages/me/bookmarks.tsx deleted file mode 100644 index fd7fe50b8e..0000000000 --- a/src/pages/me/bookmarks.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Protected } from '~/components' -import MeBookmarks from '~/views/Me/Bookmarks' - -const ProtectedMeBookMarks = () => ( - - - -) - -export default ProtectedMeBookMarks diff --git a/src/pages/me/bookmarks/articles.tsx b/src/pages/me/bookmarks/articles.tsx new file mode 100644 index 0000000000..6740dbed24 --- /dev/null +++ b/src/pages/me/bookmarks/articles.tsx @@ -0,0 +1,10 @@ +import { Protected } from '~/components' +import MeBookmarksArticles from '~/views/Me/Bookmarks/BookmarksArticles' + +const ProtectedMeBookmarksArticles = () => ( + + + +) + +export default ProtectedMeBookmarksArticles diff --git a/src/pages/me/bookmarks/index.tsx b/src/pages/me/bookmarks/index.tsx new file mode 100644 index 0000000000..e9fe9a437c --- /dev/null +++ b/src/pages/me/bookmarks/index.tsx @@ -0,0 +1,14 @@ +import { GetServerSideProps } from 'next' + +export const getServerSideProps: GetServerSideProps = async () => { + return { + redirect: { + destination: '/me/bookmarks/articles', + permanent: true, // set to false if this redirect might change in the future + }, + } +} + +export default function BookmarksRedirect() { + return null +} diff --git a/src/pages/me/bookmarks/tags.tsx b/src/pages/me/bookmarks/tags.tsx new file mode 100644 index 0000000000..818317242c --- /dev/null +++ b/src/pages/me/bookmarks/tags.tsx @@ -0,0 +1,10 @@ +import { Protected } from '~/components' +import MeBookmarksTags from '~/views/Me/Bookmarks/BookmarksTags' + +const ProtectedMeBookmarksTags = () => ( + + + +) + +export default ProtectedMeBookmarksTags diff --git a/src/views/Me/Bookmarks/index.tsx b/src/views/Me/Bookmarks/BookmarksArticles.tsx similarity index 83% rename from src/views/Me/Bookmarks/index.tsx rename to src/views/Me/Bookmarks/BookmarksArticles.tsx index 9e9596c45e..aef610348b 100644 --- a/src/views/Me/Bookmarks/index.tsx +++ b/src/views/Me/Bookmarks/BookmarksArticles.tsx @@ -13,10 +13,12 @@ import { QueryError, SpinnerBlock, } from '~/components' -import { MeBookmarkFeedQuery } from '~/gql/graphql' +import { MeBookmarkArticlesFeedQuery } from '~/gql/graphql' -const ME_BOOKMARK_FEED = gql` - query MeBookmarkFeed($after: String) { +import BookmarksTabs from './BookmarksTabs' + +const ME_BOOKMARK_ARTICLES_FEED = gql` + query MeBookmarkArticlesFeed($after: String) { viewer { id subscriptions(input: { first: 10, after: $after }) { @@ -39,9 +41,9 @@ const ME_BOOKMARK_FEED = gql` ${ArticleDigestFeed.fragments.article.private} ` -const BaseMeBookmarks = () => { +const BaseMeBookmarksArticles = () => { const { data, loading, error, fetchMore } = - useQuery(ME_BOOKMARK_FEED) + useQuery(ME_BOOKMARK_ARTICLES_FEED) if (loading) { return @@ -82,7 +84,7 @@ const BaseMeBookmarks = () => { ) } -const MeBookmarks = () => { +const MeBookmarksArticles = () => { const intl = useIntl() return ( @@ -102,11 +104,13 @@ const MeBookmarks = () => { })} /> + + - + ) } -export default MeBookmarks +export default MeBookmarksArticles diff --git a/src/views/Me/Bookmarks/BookmarksTabs.tsx b/src/views/Me/Bookmarks/BookmarksTabs.tsx new file mode 100644 index 0000000000..b507ddb8d2 --- /dev/null +++ b/src/views/Me/Bookmarks/BookmarksTabs.tsx @@ -0,0 +1,32 @@ +import { FormattedMessage } from 'react-intl' + +import { PATHS } from '~/common/enums' +import { Tabs, useRoute } from '~/components' + +const BookmarksTabs: React.FC = () => { + const { isInPath } = useRoute() + + return ( + + + + + + + + + + ) +} + +export default BookmarksTabs diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx new file mode 100644 index 0000000000..b18504e181 --- /dev/null +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -0,0 +1,117 @@ +import { useQuery } from '@apollo/react-hooks' +import gql from 'graphql-tag' +import { FormattedMessage, useIntl } from 'react-intl' + +import { mergeConnections } from '~/common/utils' +import { + ArticleDigestFeed, + EmptyBookmark, + Head, + InfiniteScroll, + Layout, + List, + QueryError, + SpinnerBlock, +} from '~/components' +import { MeBookmarkTagsFeedQuery } from '~/gql/graphql' + +import BookmarksTabs from './BookmarksTabs' + +const ME_BOOKMARK_TAGS_FEED = gql` + query MeBookmarkTagsFeed($after: String) { + viewer { + id + subscriptions(input: { first: 10, after: $after }) { + pageInfo { + startCursor + endCursor + hasNextPage + } + edges { + cursor + node { + ...ArticleDigestFeedArticlePublic + ...ArticleDigestFeedArticlePrivate + } + } + } + } + } + ${ArticleDigestFeed.fragments.article.public} + ${ArticleDigestFeed.fragments.article.private} +` + +const BaseMeBookmarksTags = () => { + const { data, loading, error, fetchMore } = useQuery( + ME_BOOKMARK_TAGS_FEED + ) + + if (loading) { + return + } + + if (error) { + return + } + + const connectionPath = 'viewer.subscriptions' + const { edges, pageInfo } = data?.viewer?.subscriptions || {} + + if (!edges || edges.length <= 0 || !pageInfo) { + return + } + + const loadMore = () => + fetchMore({ + variables: { after: pageInfo.endCursor }, + updateQuery: (previousResult, { fetchMoreResult }) => + mergeConnections({ + oldData: previousResult, + newData: fetchMoreResult, + path: connectionPath, + }), + }) + + return ( + + + {edges.map(({ node, cursor }) => ( + + + + ))} + + + ) +} + +const MeBookmarksTags = () => { + const intl = useIntl() + + return ( + + + + + } + /> + + + + + + + + + + ) +} + +export default MeBookmarksTags From 3567a9bfa699db0f752ee9e5eb183fe81e962fab Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:42:38 +0800 Subject: [PATCH 42/69] refactor(TagDigest): remove TagDigest.Rich component --- src/components/TagDigest/Rich/Rich.test.tsx | 41 ---------- src/components/TagDigest/Rich/index.tsx | 80 ------------------- .../TagDigest/Rich/styles.module.css | 30 ------- src/components/TagDigest/index.tsx | 2 - .../components/TagDigest/Rich.stories.tsx | 29 ------- 5 files changed, 182 deletions(-) delete mode 100644 src/components/TagDigest/Rich/Rich.test.tsx delete mode 100644 src/components/TagDigest/Rich/index.tsx delete mode 100644 src/components/TagDigest/Rich/styles.module.css delete mode 100644 src/stories/components/TagDigest/Rich.stories.tsx diff --git a/src/components/TagDigest/Rich/Rich.test.tsx b/src/components/TagDigest/Rich/Rich.test.tsx deleted file mode 100644 index 7511767274..0000000000 --- a/src/components/TagDigest/Rich/Rich.test.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import mockRouter from 'next-router-mock' -import { describe, expect, it } from 'vitest' - -import { TEST_ID } from '~/common/enums' -import { render, screen } from '~/common/utils/test' -import { TagDigest } from '~/components' -import { MOCK_TAG } from '~/stories/mocks' - -describe('', () => { - it('should render a TagDigest.Rich', () => { - render() - - const $digest = screen.getByTestId(TEST_ID.DIGEST_TAG_RICH) - expect($digest).toBeInTheDocument() - $digest.click() - expect(mockRouter.asPath).toContain(MOCK_TAG.slug) - - const $name = screen.getByText(MOCK_TAG.content) - expect($name).toBeInTheDocument() - - const $followButton = screen.getByText('Follow') - expect($followButton).toBeInTheDocument() - }) - - it('should render a TagDigest.Rich without description', () => { - render() - - const $digest = screen.getByTestId(TEST_ID.DIGEST_TAG_RICH) - expect($digest).toBeInTheDocument() - }) - - it('should render a TagDigest.Rich without follow button', () => { - render() - - const $digest = screen.getByTestId(TEST_ID.DIGEST_TAG_RICH) - expect($digest).toBeInTheDocument() - - const $followButton = screen.queryByText('Follow') - expect($followButton).not.toBeInTheDocument() - }) -}) diff --git a/src/components/TagDigest/Rich/index.tsx b/src/components/TagDigest/Rich/index.tsx deleted file mode 100644 index dcfa83606e..0000000000 --- a/src/components/TagDigest/Rich/index.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import gql from 'graphql-tag' - -import { ReactComponent as IconHashTag } from '@/public/static/icons/24px/hashtag.svg' -import { TEST_ID } from '~/common/enums' -import { toPath } from '~/common/utils' -import { Card, CardProps, Icon, TextIcon } from '~/components' -import { - TagDigestRichTagPrivateFragment, - TagDigestRichTagPublicFragment, -} from '~/gql/graphql' - -import { TagDigestButtons } from '../Buttons' -import styles from './styles.module.css' - -type Props = { - tag: TagDigestRichTagPublicFragment & Partial - - hasFollow?: boolean -} & CardProps - -const fragments = { - tag: { - public: gql` - fragment TagDigestRichTagPublic on Tag { - id - content - } - `, - private: gql` - fragment TagDigestRichTagPrivate on Tag { - id - ...TagDigestFollowButtonPrivate - } - ${TagDigestButtons.FollowButton.fragments.tag.private} - `, - }, -} - -const Rich = ({ - tag, - hasFollow, - - ...cardProps -}: Props) => { - const path = toPath({ - page: 'tagDetail', - tag, - }) - - return ( - -
    - } - color="black" - size={16} - spacing={4} - weight="normal" - > - {tag.content} - - - {hasFollow && ( -
    - -
    - )} -
    -
    - ) -} - -Rich.fragments = fragments - -export default Rich diff --git a/src/components/TagDigest/Rich/styles.module.css b/src/components/TagDigest/Rich/styles.module.css deleted file mode 100644 index 2a0da74d66..0000000000 --- a/src/components/TagDigest/Rich/styles.module.css +++ /dev/null @@ -1,30 +0,0 @@ -.content { - & .text { - @mixin line-clamp; - - line-height: inherit; - } - - position: relative; - display: block; - padding-right: 3rem; - - & .button { - @mixin inline-flex-center-all; - - position: absolute; - top: 0; - right: 0; - bottom: 0; - justify-content: flex-end; - width: 3rem; - } -} - -.desc { - @mixin line-clamp; - - margin: var(--sp4) 0 0 1.25rem; - font-size: var(--text13); - color: var(--color-grey-darker); -} diff --git a/src/components/TagDigest/index.tsx b/src/components/TagDigest/index.tsx index f5fd06a8db..93ced8b35f 100644 --- a/src/components/TagDigest/index.tsx +++ b/src/components/TagDigest/index.tsx @@ -1,11 +1,9 @@ import Concise from './Concise' import Feed from './Feed' -import Rich from './Rich' import Sidebar from './Sidebar' export const TagDigest = { Concise, - Rich, Sidebar, Feed, } diff --git a/src/stories/components/TagDigest/Rich.stories.tsx b/src/stories/components/TagDigest/Rich.stories.tsx deleted file mode 100644 index 7b3d8e6d28..0000000000 --- a/src/stories/components/TagDigest/Rich.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { MockedProvider } from '@apollo/react-testing' -import { ComponentMeta, ComponentStory } from '@storybook/react' -import React from 'react' - -import { TagDigest } from '~/components' - -import { MOCK_TAG } from '../../mocks' - -export default { - title: 'Components/TagDigest/Rich', - component: TagDigest.Rich, -} as ComponentMeta - -const Template: ComponentStory = (args) => ( - - - -) - -export const Default = Template.bind({}) -Default.args = { - tag: MOCK_TAG as any, -} - -export const HasFollow = Template.bind({}) -HasFollow.args = { - tag: MOCK_TAG as any, - hasFollow: true, -} From 299390acc01ce1eef8fb2bf0f8238d585fbff8d4 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:42:58 +0800 Subject: [PATCH 43/69] feat(TagDigest): add Bookmark component --- src/common/enums/test.ts | 1 + .../Buttons/TagBookmark/Bookmark.tsx | 78 +++++++++++++++++++ .../Buttons/TagBookmark/Unbookmark.tsx | 61 +++++++++++++++ src/components/Buttons/TagBookmark/index.tsx | 31 ++++++++ src/components/Buttons/index.tsx | 1 + .../TagDigest/Bookmark/Bookmark.test.tsx | 0 src/components/TagDigest/Bookmark/index.tsx | 52 +++++++++++++ .../TagDigest/Bookmark/styles.module.css | 13 ++++ src/components/TagDigest/index.tsx | 2 + .../components/TagDigest/Bookmark.stories.tsx | 40 ++++++++++ 10 files changed, 279 insertions(+) create mode 100644 src/components/Buttons/TagBookmark/Bookmark.tsx create mode 100644 src/components/Buttons/TagBookmark/Unbookmark.tsx create mode 100644 src/components/Buttons/TagBookmark/index.tsx create mode 100644 src/components/TagDigest/Bookmark/Bookmark.test.tsx create mode 100644 src/components/TagDigest/Bookmark/index.tsx create mode 100644 src/components/TagDigest/Bookmark/styles.module.css create mode 100644 src/stories/components/TagDigest/Bookmark.stories.tsx diff --git a/src/common/enums/test.ts b/src/common/enums/test.ts index c5634f3469..3cb983ce83 100644 --- a/src/common/enums/test.ts +++ b/src/common/enums/test.ts @@ -31,6 +31,7 @@ export enum TEST_ID { DIGEST_USER_RICH_DISPLAY_NAME = 'digest/user/rich/display-name', DIGEST_USER_VERBOSE = 'digest/user/verbose', DIGEST_TAG_CONCISE = 'digest/tag/concise', + DIGEST_TAG_BOOKMARK = 'digest/tag/bookmark', DIGEST_TAG_FEED = 'digest/tag/feed', DIGEST_TAG_FEED_NUM_ARTICLES = 'digest/tag/feed/num-articles', DIGEST_TAG_RICH = 'digest/tag/rich', diff --git a/src/components/Buttons/TagBookmark/Bookmark.tsx b/src/components/Buttons/TagBookmark/Bookmark.tsx new file mode 100644 index 0000000000..3e167b90e8 --- /dev/null +++ b/src/components/Buttons/TagBookmark/Bookmark.tsx @@ -0,0 +1,78 @@ +import _isNil from 'lodash/isNil' +import { useContext } from 'react' +import { useIntl } from 'react-intl' + +import { ReactComponent as IconSave } from '@/public/static/icons/24px/save.svg' +import { + OPEN_UNIVERSAL_AUTH_DIALOG, + UNIVERSAL_AUTH_TRIGGER, +} from '~/common/enums' +import { Button, Icon, toast, useMutation, ViewerContext } from '~/components' +import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' +import { + TagBookmarkButtonTagPrivateFragment, + ToggleBookmarkTagMutation, +} from '~/gql/graphql' + +interface BookmarkProps { + tag: TagBookmarkButtonTagPrivateFragment +} + +const Bookmark = ({ tag }: BookmarkProps) => { + const viewer = useContext(ViewerContext) + const intl = useIntl() + const [bookmark] = useMutation( + TOGGLE_BOOKMARK_TAG, + { + variables: { id: tag.id, enabled: true }, + optimisticResponse: + !_isNil(tag.id) && !_isNil(tag.isFollower) + ? { + toggleBookmarkTag: { + id: tag.id, + isFollower: true, + __typename: 'Tag', + }, + } + : undefined, + } + ) + + const onClick = async () => { + if (!viewer.isAuthed) { + window.dispatchEvent( + new CustomEvent(OPEN_UNIVERSAL_AUTH_DIALOG, { + detail: { trigger: UNIVERSAL_AUTH_TRIGGER.bookmarkTag }, + }) + ) + return + } + + await bookmark() + + toast.success({ + message: intl.formatMessage({ + defaultMessage: 'Bookmarked', + id: 'k0fraU', + }), + }) + } + + return ( + + ) +} + +export default Bookmark diff --git a/src/components/Buttons/TagBookmark/Unbookmark.tsx b/src/components/Buttons/TagBookmark/Unbookmark.tsx new file mode 100644 index 0000000000..09d3289208 --- /dev/null +++ b/src/components/Buttons/TagBookmark/Unbookmark.tsx @@ -0,0 +1,61 @@ +import _isNil from 'lodash/isNil' +import { useIntl } from 'react-intl' + +import { ReactComponent as IconSave2 } from '@/public/static/icons/24px/save2.svg' +import { Button, Icon, toast, useMutation } from '~/components' +import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' +import { + TagBookmarkButtonTagPrivateFragment, + ToggleBookmarkTagMutation, +} from '~/gql/graphql' + +interface UnbookmarkTagProps { + tag: TagBookmarkButtonTagPrivateFragment +} + +const Unbookmark = ({ tag }: UnbookmarkTagProps) => { + const intl = useIntl() + const [unbookmark] = useMutation( + TOGGLE_BOOKMARK_TAG, + { + variables: { id: tag.id, enabled: false }, + optimisticResponse: + !_isNil(tag.id) && !_isNil(tag.isFollower) + ? { + toggleBookmarkTag: { + id: tag.id, + isFollower: false, + __typename: 'Tag', + }, + } + : undefined, + } + ) + const onClick = async () => { + await unbookmark() + toast.success({ + message: intl.formatMessage({ + defaultMessage: 'Bookmark removed', + id: '8ZyDQJ', + }), + }) + } + + return ( + + ) +} + +export default Unbookmark diff --git a/src/components/Buttons/TagBookmark/index.tsx b/src/components/Buttons/TagBookmark/index.tsx new file mode 100644 index 0000000000..07704b538e --- /dev/null +++ b/src/components/Buttons/TagBookmark/index.tsx @@ -0,0 +1,31 @@ +import gql from 'graphql-tag' + +import { TagBookmarkButtonTagPrivateFragment } from '~/gql/graphql' + +import Bookmark from './Bookmark' +import Unbookmark from './Unbookmark' + +interface TagBookmarkButtonProps { + tag: TagBookmarkButtonTagPrivateFragment +} + +const fragments = { + tag: { + private: gql` + fragment TagBookmarkButtonTagPrivate on Tag { + id + isFollower + } + `, + }, +} + +export const TagBookmarkButton = ({ tag }: TagBookmarkButtonProps) => { + if (tag.isFollower) { + return + } else { + return + } +} + +TagBookmarkButton.fragments = fragments diff --git a/src/components/Buttons/index.tsx b/src/components/Buttons/index.tsx index c0f06f11f2..025fd353f7 100644 --- a/src/components/Buttons/index.tsx +++ b/src/components/Buttons/index.tsx @@ -8,6 +8,7 @@ export * from './Share' export * from './Shuffle' export * from './SignUp' export * from './StartWriting' +export * from './TagBookmark' export * from './UniversalAuth' export * from './ViewAll' export * from './ViewMore' diff --git a/src/components/TagDigest/Bookmark/Bookmark.test.tsx b/src/components/TagDigest/Bookmark/Bookmark.test.tsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/components/TagDigest/Bookmark/index.tsx b/src/components/TagDigest/Bookmark/index.tsx new file mode 100644 index 0000000000..8f9568666c --- /dev/null +++ b/src/components/TagDigest/Bookmark/index.tsx @@ -0,0 +1,52 @@ +import gql from 'graphql-tag' +import Link from 'next/link' + +import { TEST_ID } from '~/common/enums' +import { toPath } from '~/common/utils' +import { TagBookmarkButton } from '~/components/Buttons/TagBookmark' +import { TagDigestBookmarkTagFragment } from '~/gql/graphql' + +import styles from './styles.module.css' + +export type TagDigestBookmarkProps = { + tag: TagDigestBookmarkTagFragment + onClick?: () => void +} + +const fragments = { + tag: gql` + fragment TagDigestBookmarkTag on Tag { + id + content + ...TagBookmarkButtonTagPrivate + } + ${TagBookmarkButton.fragments.tag.private} + `, +} + +const Bookmark = ({ tag, onClick }: TagDigestBookmarkProps) => { + const path = toPath({ + page: 'tagDetail', + tag, + }) + + return ( +
    + + + {tag.content} + + +
    + +
    +
    + ) +} + +Bookmark.fragments = fragments + +export default Bookmark diff --git a/src/components/TagDigest/Bookmark/styles.module.css b/src/components/TagDigest/Bookmark/styles.module.css new file mode 100644 index 0000000000..30cc62357b --- /dev/null +++ b/src/components/TagDigest/Bookmark/styles.module.css @@ -0,0 +1,13 @@ +.container { + @mixin flex-center-space-between; + + & .tag { + @mixin line-clamp; + + line-height: 1.5rem; + + &:hover { + color: var(--color-matters-green); + } + } +} diff --git a/src/components/TagDigest/index.tsx b/src/components/TagDigest/index.tsx index f5fd06a8db..ab97a6f9cb 100644 --- a/src/components/TagDigest/index.tsx +++ b/src/components/TagDigest/index.tsx @@ -1,3 +1,4 @@ +import Bookmark from './Bookmark' import Concise from './Concise' import Feed from './Feed' import Rich from './Rich' @@ -5,6 +6,7 @@ import Sidebar from './Sidebar' export const TagDigest = { Concise, + Bookmark, Rich, Sidebar, Feed, diff --git a/src/stories/components/TagDigest/Bookmark.stories.tsx b/src/stories/components/TagDigest/Bookmark.stories.tsx new file mode 100644 index 0000000000..d8d57c02ee --- /dev/null +++ b/src/stories/components/TagDigest/Bookmark.stories.tsx @@ -0,0 +1,40 @@ +import { MockedProvider } from '@apollo/react-testing' +import { ComponentMeta, ComponentStory } from '@storybook/react' +import React from 'react' + +import { TagDigest } from '~/components' + +import { MOCK_TAG } from '../../mocks' + +export default { + title: 'Components/TagDigest/Bookmark', + component: TagDigest.Bookmark, +} as ComponentMeta + +const Template: ComponentStory = (args) => ( + + + +) + +export const Default = Template.bind({}) +Default.args = { + tag: MOCK_TAG as any, +} + +export const HasFollow = Template.bind({}) +HasFollow.args = { + tag: { + ...MOCK_TAG, + isFollower: true, + } as any, +} + +export const LongTagName = Template.bind({}) +LongTagName.args = { + tag: { + ...MOCK_TAG, + content: + 'LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName LongTagName', + } as any, +} From ee292c81163ee76309bde1e1b356be56c655c6f3 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:48:13 +0800 Subject: [PATCH 44/69] feat(TagDetail): migrate TagDetailButtons.BookmarkButton to TagBookmarkButton component --- .../Buttons/BookmarkButton/Bookmark.tsx | 78 ------------------- .../Buttons/BookmarkButton/Unbookmark.tsx | 61 --------------- .../Buttons/BookmarkButton/index.tsx | 33 -------- src/views/TagDetail/Buttons/index.tsx | 5 -- src/views/TagDetail/gql.ts | 11 +-- src/views/TagDetail/index.tsx | 4 +- 6 files changed, 8 insertions(+), 184 deletions(-) delete mode 100644 src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx delete mode 100644 src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx delete mode 100644 src/views/TagDetail/Buttons/BookmarkButton/index.tsx delete mode 100644 src/views/TagDetail/Buttons/index.tsx diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx deleted file mode 100644 index 27fec490d0..0000000000 --- a/src/views/TagDetail/Buttons/BookmarkButton/Bookmark.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import _isNil from 'lodash/isNil' -import { useContext } from 'react' -import { useIntl } from 'react-intl' - -import { ReactComponent as IconSave } from '@/public/static/icons/24px/save.svg' -import { - OPEN_UNIVERSAL_AUTH_DIALOG, - UNIVERSAL_AUTH_TRIGGER, -} from '~/common/enums' -import { Button, Icon, toast, useMutation, ViewerContext } from '~/components' -import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' -import { - BookmarkButtonTagPrivateFragment, - ToggleBookmarkTagMutation, -} from '~/gql/graphql' - -interface BookmarkProps { - tag: BookmarkButtonTagPrivateFragment -} - -const Bookmark = ({ tag }: BookmarkProps) => { - const viewer = useContext(ViewerContext) - const intl = useIntl() - const [bookmark] = useMutation( - TOGGLE_BOOKMARK_TAG, - { - variables: { id: tag.id, enabled: true }, - optimisticResponse: - !_isNil(tag.id) && !_isNil(tag.isFollower) - ? { - toggleBookmarkTag: { - id: tag.id, - isFollower: true, - __typename: 'Tag', - }, - } - : undefined, - } - ) - - const onClick = async () => { - if (!viewer.isAuthed) { - window.dispatchEvent( - new CustomEvent(OPEN_UNIVERSAL_AUTH_DIALOG, { - detail: { trigger: UNIVERSAL_AUTH_TRIGGER.bookmarkTag }, - }) - ) - return - } - - await bookmark() - - toast.success({ - message: intl.formatMessage({ - defaultMessage: 'Bookmarked', - id: 'k0fraU', - }), - }) - } - - return ( - - ) -} - -export default Bookmark diff --git a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx b/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx deleted file mode 100644 index 3d29adc871..0000000000 --- a/src/views/TagDetail/Buttons/BookmarkButton/Unbookmark.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import _isNil from 'lodash/isNil' -import { useIntl } from 'react-intl' - -import { ReactComponent as IconSave2 } from '@/public/static/icons/24px/save2.svg' -import { Button, Icon, toast, useMutation } from '~/components' -import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' -import { - BookmarkButtonTagPrivateFragment, - ToggleBookmarkTagMutation, -} from '~/gql/graphql' - -interface UnbookmarkTagProps { - tag: BookmarkButtonTagPrivateFragment -} - -const Unbookmark = ({ tag }: UnbookmarkTagProps) => { - const intl = useIntl() - const [unbookmark] = useMutation( - TOGGLE_BOOKMARK_TAG, - { - variables: { id: tag.id, enabled: false }, - optimisticResponse: - !_isNil(tag.id) && !_isNil(tag.isFollower) - ? { - toggleBookmarkTag: { - id: tag.id, - isFollower: false, - __typename: 'Tag', - }, - } - : undefined, - } - ) - const onClick = async () => { - await unbookmark() - toast.success({ - message: intl.formatMessage({ - defaultMessage: 'Bookmark removed', - id: '8ZyDQJ', - }), - }) - } - - return ( - - ) -} - -export default Unbookmark diff --git a/src/views/TagDetail/Buttons/BookmarkButton/index.tsx b/src/views/TagDetail/Buttons/BookmarkButton/index.tsx deleted file mode 100644 index 0ec96f02c4..0000000000 --- a/src/views/TagDetail/Buttons/BookmarkButton/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import gql from 'graphql-tag' - -import { BookmarkButtonTagPrivateFragment } from '~/gql/graphql' - -import Bookmark from './Bookmark' -import Unbookmark from './Unbookmark' - -interface FollowButtonProps { - tag: BookmarkButtonTagPrivateFragment -} - -const fragments = { - tag: { - private: gql` - fragment BookmarkButtonTagPrivate on Tag { - id - isFollower - } - `, - }, -} - -const FollowButton = ({ tag }: FollowButtonProps) => { - if (tag.isFollower) { - return - } else { - return - } -} - -FollowButton.fragments = fragments - -export default FollowButton diff --git a/src/views/TagDetail/Buttons/index.tsx b/src/views/TagDetail/Buttons/index.tsx deleted file mode 100644 index 1044007be3..0000000000 --- a/src/views/TagDetail/Buttons/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import BookmarkButton from './BookmarkButton' - -export const TagDetailButtons = { - BookmarkButton, -} diff --git a/src/views/TagDetail/gql.ts b/src/views/TagDetail/gql.ts index 6df71da98f..c37e5936fa 100644 --- a/src/views/TagDetail/gql.ts +++ b/src/views/TagDetail/gql.ts @@ -1,7 +1,8 @@ import gql from 'graphql-tag' +import { TagBookmarkButton } from '~/components' + import ArticlesCount from './ArticlesCount' -import { TagDetailButtons } from './Buttons' const tagFragment = gql` fragment TagFragment on Tag { @@ -13,7 +14,7 @@ const tagFragment = gql` totalCount } ...ArticleCountTag - ...BookmarkButtonTagPrivate + ...TagBookmarkButtonTagPrivate recommended(input: { first: 10 }) { edges { cursor @@ -27,7 +28,7 @@ const tagFragment = gql` } } ${ArticlesCount.fragments.tag} - ${TagDetailButtons.BookmarkButton.fragments.tag.private} + ${TagBookmarkButton.fragments.tag.private} ` export const TAG_DETAIL_PUBLIC = gql` @@ -62,9 +63,9 @@ export const TAG_DETAIL_PRIVATE = gql` node(input: { id: $id }) { ... on Tag { id - ...BookmarkButtonTagPrivate + ...TagBookmarkButtonTagPrivate } } } - ${TagDetailButtons.BookmarkButton.fragments.tag.private} + ${TagBookmarkButton.fragments.tag.private} ` diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index a966f9eb80..48d2d3265a 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -13,6 +13,7 @@ import { Layout, SpinnerBlock, SquareTabs, + TagBookmarkButton, TextIcon, Throw404, usePublicQuery, @@ -28,7 +29,6 @@ import { import TagDetailArticles from './Articles' import ArticlesCount from './ArticlesCount' -import { TagDetailButtons } from './Buttons' import { TAG_DETAIL_BY_SEARCH, TAG_DETAIL_PRIVATE, @@ -125,7 +125,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => {
    - +
    {hasArticles && ( From 144cb1734a40628ab3e33c1fbc1e31c684156a50 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:20:27 +0700 Subject: [PATCH 45/69] fix(campaign): dedup participant list if total count is less than maxAvatarCount --- src/views/CampaignDetail/SideParticipants/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/CampaignDetail/SideParticipants/index.tsx b/src/views/CampaignDetail/SideParticipants/index.tsx index 5181248209..af0c3037ba 100644 --- a/src/views/CampaignDetail/SideParticipants/index.tsx +++ b/src/views/CampaignDetail/SideParticipants/index.tsx @@ -86,7 +86,7 @@ const SideParticipants = ({ campaign }: SideParticipantsProps) => { } if (edges.length <= maxAvatarCount) { - return edges + return edges.filter(({ node }) => node.id !== viewer.id) } const withAvatars = edges.filter( From 5c56b1f65f6f64801dda42867728ce8cf3193855 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:20:27 +0700 Subject: [PATCH 46/69] fix(campaign): dedup participant list if total count is less than maxAvatarCount --- src/views/CampaignDetail/SideParticipants/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/CampaignDetail/SideParticipants/index.tsx b/src/views/CampaignDetail/SideParticipants/index.tsx index 5181248209..af0c3037ba 100644 --- a/src/views/CampaignDetail/SideParticipants/index.tsx +++ b/src/views/CampaignDetail/SideParticipants/index.tsx @@ -86,7 +86,7 @@ const SideParticipants = ({ campaign }: SideParticipantsProps) => { } if (edges.length <= maxAvatarCount) { - return edges + return edges.filter(({ node }) => node.id !== viewer.id) } const withAvatars = edges.filter( From b74fe02399a7fa443d71ff17e52080f10f6ff1db Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:22:36 +0800 Subject: [PATCH 47/69] feat(Bookmark): update bookmarks tag view to use TagDigest.Bookmark --- .../TagDigest/Bookmark/styles.module.css | 3 ++ src/views/Me/Bookmarks/BookmarksTags.tsx | 34 +++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/components/TagDigest/Bookmark/styles.module.css b/src/components/TagDigest/Bookmark/styles.module.css index 30cc62357b..6c966321a5 100644 --- a/src/components/TagDigest/Bookmark/styles.module.css +++ b/src/components/TagDigest/Bookmark/styles.module.css @@ -1,9 +1,12 @@ .container { @mixin flex-center-space-between; + padding: var(--sp16) 0; + & .tag { @mixin line-clamp; + flex-grow: 1; line-height: 1.5rem; &:hover { diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx index b18504e181..dd21b590d3 100644 --- a/src/views/Me/Bookmarks/BookmarksTags.tsx +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -4,7 +4,6 @@ import { FormattedMessage, useIntl } from 'react-intl' import { mergeConnections } from '~/common/utils' import { - ArticleDigestFeed, EmptyBookmark, Head, InfiniteScroll, @@ -12,6 +11,7 @@ import { List, QueryError, SpinnerBlock, + TagDigest, } from '~/components' import { MeBookmarkTagsFeedQuery } from '~/gql/graphql' @@ -21,24 +21,24 @@ const ME_BOOKMARK_TAGS_FEED = gql` query MeBookmarkTagsFeed($after: String) { viewer { id - subscriptions(input: { first: 10, after: $after }) { - pageInfo { - startCursor - endCursor - hasNextPage - } - edges { - cursor - node { - ...ArticleDigestFeedArticlePublic - ...ArticleDigestFeedArticlePrivate + following { + tags(input: { first: 20, after: $after }) { + pageInfo { + startCursor + endCursor + hasNextPage + } + edges { + cursor + node { + ...TagDigestBookmarkTag + } } } } } } - ${ArticleDigestFeed.fragments.article.public} - ${ArticleDigestFeed.fragments.article.private} + ${TagDigest.Bookmark.fragments.tag} ` const BaseMeBookmarksTags = () => { @@ -54,8 +54,8 @@ const BaseMeBookmarksTags = () => { return } - const connectionPath = 'viewer.subscriptions' - const { edges, pageInfo } = data?.viewer?.subscriptions || {} + const connectionPath = 'viewer.following.tags' + const { edges, pageInfo } = data?.viewer?.following?.tags || {} if (!edges || edges.length <= 0 || !pageInfo) { return @@ -77,7 +77,7 @@ const BaseMeBookmarksTags = () => { {edges.map(({ node, cursor }) => ( - + ))} From d9c2164ac6c7533f538789484bdae050f1f51612 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:35:35 +0800 Subject: [PATCH 48/69] fix(bookmarks): add isFollower check and improve private data loading --- src/views/Me/Bookmarks/BookmarksTags.tsx | 10 +++++++--- src/views/TagDetail/index.tsx | 20 +++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx index dd21b590d3..f5b36991c2 100644 --- a/src/views/Me/Bookmarks/BookmarksTags.tsx +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -76,9 +76,13 @@ const BaseMeBookmarksTags = () => { {edges.map(({ node, cursor }) => ( - - - + <> + {node.isFollower && ( + + + + )} + ))} diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index 48d2d3265a..26a008f370 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -160,6 +160,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const TagDetailContainer = () => { const viewer = useContext(ViewerContext) const { getQuery } = useRoute() + const [, setPrivateDataLoaded] = useState(false) // backward compatible with: // - `/tags/:globalId:` @@ -206,24 +207,29 @@ const TagDetailContainer = () => { ) // private data - const loadPrivate = (id: string) => { + const loadPrivate = async (id: string) => { if (!viewer.isAuthed || !id) { return } - client.query({ - query: TAG_DETAIL_PRIVATE, - fetchPolicy: 'network-only', - variables: { id }, - }) + try { + await client.query({ + query: TAG_DETAIL_PRIVATE, + fetchPolicy: 'network-only', + variables: { id }, + }) + setPrivateDataLoaded(true) + } catch (error) { + console.error('Error loading private data:', error) + } } const searchedTag = resultBySearch?.data?.search.edges?.[0] .node as TagFragmentFragment - // fetch private data for first page useEffect(() => { const retryTagId = tagId || searchedTag?.id if (retryTagId) { + setPrivateDataLoaded(false) loadPrivate(retryTagId) } }, [tagId, resultBySearch?.data, viewer.id]) From 2c490383e07869b2c89ac8b729a978c3b15900ac Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:56:21 +0800 Subject: [PATCH 49/69] fix(i18n): update copy --- lang/zh-Hans.json | 2 +- lang/zh-Hant.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 54683fa38f..3a9b30715c 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -766,7 +766,7 @@ "defaultMessage": "在动态留言中提及了你 {commentMoment}" }, "Ajc5SE": { - "defaultMessage": "Articles", + "defaultMessage": "作品", "description": "src/views/Me/Bookmarks/Tabs.tsx" }, "AlHYvk": { diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 4cdf24c30e..6a769d5231 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -766,7 +766,7 @@ "defaultMessage": "在動態留言中提及了你 {commentMoment}" }, "Ajc5SE": { - "defaultMessage": "Articles", + "defaultMessage": "作品", "description": "src/views/Me/Bookmarks/Tabs.tsx" }, "AlHYvk": { From 917995dd30b9bad18635e9f61ae1948769938621 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:22:53 +0800 Subject: [PATCH 50/69] feat(TagDigest): add Bookmark component tests --- .../TagDigest/Bookmark/Bookmark.test.tsx | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/components/TagDigest/Bookmark/Bookmark.test.tsx b/src/components/TagDigest/Bookmark/Bookmark.test.tsx index e69de29bb2..de25ee0cf4 100644 --- a/src/components/TagDigest/Bookmark/Bookmark.test.tsx +++ b/src/components/TagDigest/Bookmark/Bookmark.test.tsx @@ -0,0 +1,51 @@ +import { MockedProvider } from '@apollo/react-testing' +import { render, screen } from '@testing-library/react' +import { IntlProvider } from 'react-intl' +import { describe, expect, it } from 'vitest' + +import { TEST_ID } from '~/common/enums' +import { TagDigest } from '~/components' +import { MOCK_TAG } from '~/stories/mocks' + +describe('', () => { + it('should render a TagDigest.Bookmark', () => { + render( + + + + + + ) + + const $bookmark = screen.getByTestId(TEST_ID.DIGEST_TAG_BOOKMARK) + expect($bookmark).toBeInTheDocument() + + const $name = screen.getByText(MOCK_TAG.content) + expect($name).toBeInTheDocument() + + const $bookmarkButton = screen.getByRole('button', { + name: 'Bookmark', + }) + expect($bookmarkButton).toBeInTheDocument() + }) + + it('should render a TagDigest.Bookmark with isFollower', () => { + render( + + + + + + ) + + const $bookmarkButton = screen.getByRole('button', { + name: 'Remove bookmark', + }) + expect($bookmarkButton).toBeInTheDocument() + }) +}) From c315aa277440f88aab9b9ae86ff36ffca2a1f28a Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:01:42 +0800 Subject: [PATCH 51/69] fix(TagDetail): delay private data loading to ensure proper state updates in TagDetail component --- src/views/TagDetail/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index 26a008f370..1d7cc8c748 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -160,7 +160,6 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const TagDetailContainer = () => { const viewer = useContext(ViewerContext) const { getQuery } = useRoute() - const [, setPrivateDataLoaded] = useState(false) // backward compatible with: // - `/tags/:globalId:` @@ -218,7 +217,6 @@ const TagDetailContainer = () => { fetchPolicy: 'network-only', variables: { id }, }) - setPrivateDataLoaded(true) } catch (error) { console.error('Error loading private data:', error) } @@ -229,8 +227,10 @@ const TagDetailContainer = () => { useEffect(() => { const retryTagId = tagId || searchedTag?.id if (retryTagId) { - setPrivateDataLoaded(false) - loadPrivate(retryTagId) + // FIXME: Delayed loading of private data allows private data to guarantee writing to the final result + setTimeout(() => { + loadPrivate(retryTagId) + }, 100) } }, [tagId, resultBySearch?.data, viewer.id]) From 5733db90f447209c46ac72f02b1287ee11ba9e11 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:08:31 +0800 Subject: [PATCH 52/69] fix: adjust padding and max-width for last items in grid layouts --- .../Search/AggregateResults/styles.module.css | 16 ++++++++++++++++ src/views/Tags/styles.module.css | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/views/Search/AggregateResults/styles.module.css b/src/views/Search/AggregateResults/styles.module.css index 496aa57c27..bc4162c781 100644 --- a/src/views/Search/AggregateResults/styles.module.css +++ b/src/views/Search/AggregateResults/styles.module.css @@ -56,6 +56,14 @@ &:nth-child(2n + 1) { padding-right: var(--sp16); } + + &:last-child { + padding-right: 0; + + & a { + max-width: calc(50% - var(--sp16)); + } + } } } @@ -67,6 +75,14 @@ &:nth-child(3n + 2) { padding-right: var(--sp16); } + + &:last-child { + padding-right: 0; + + & a { + max-width: calc(33.3333% - var(--sp16)); + } + } } } } diff --git a/src/views/Tags/styles.module.css b/src/views/Tags/styles.module.css index 12bde92ba2..0c882e9a39 100644 --- a/src/views/Tags/styles.module.css +++ b/src/views/Tags/styles.module.css @@ -29,6 +29,14 @@ &:nth-child(2n + 1) { padding-right: var(--sp16); } + + &:last-child { + padding-right: 0; + + & a { + max-width: calc(50% - var(--sp16)); + } + } } } @@ -40,6 +48,14 @@ &:nth-child(3n + 2) { padding-right: var(--sp16); } + + &:last-child { + padding-right: 0; + + & a { + max-width: calc(33.3333% - var(--sp16)); + } + } } } } From a2829dbfebc4ac1e054c4aa1165089ffe69d9b57 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:34:40 +0800 Subject: [PATCH 53/69] refactor: extract Infinite Scroll Logic into Reusable Component --- src/components/TagList/InfiniteTagList.tsx | 64 +++++++++++++++++++ src/components/TagList/index.tsx | 5 ++ src/components/TagList/styles.module.css | 54 ++++++++++++++++ src/components/index.tsx | 1 + src/views/Search/AggregateResults/Tags.tsx | 41 +++--------- .../Search/AggregateResults/styles.module.css | 55 ---------------- src/views/Tags/Feed.tsx | 31 ++------- src/views/Tags/styles.module.css | 54 ---------------- 8 files changed, 138 insertions(+), 167 deletions(-) create mode 100644 src/components/TagList/InfiniteTagList.tsx create mode 100644 src/components/TagList/index.tsx create mode 100644 src/components/TagList/styles.module.css diff --git a/src/components/TagList/InfiniteTagList.tsx b/src/components/TagList/InfiniteTagList.tsx new file mode 100644 index 0000000000..5e0ea8c9ac --- /dev/null +++ b/src/components/TagList/InfiniteTagList.tsx @@ -0,0 +1,64 @@ +import { FormattedMessage } from 'react-intl' + +import { analytics } from '~/common/utils' +import { InfiniteScroll, TagDigest } from '~/components' + +import styles from './styles.module.css' + +interface Props { + edges: Array<{ node: any; cursor?: string }> + pageInfo: { + hasNextPage: boolean + endCursor?: string | null + } + loadMore: () => Promise + trackingType: 'search_tag' | 'all_tags' | 'all_tags_recommended' + searchKey?: string + maxResults?: number + showEOFMessage?: boolean +} + +const InfiniteTagList = ({ + edges, + pageInfo, + loadMore, + trackingType, + searchKey, + maxResults = Infinity, + showEOFMessage = true, +}: Props) => { + return ( + + ) + } + > +
      + {edges.map(({ node, cursor }, i) => + node.__typename === 'Tag' ? ( +
    • + + analytics.trackEvent('click_feed', { + type: trackingType, + contentType: 'tag', + location: i, + id: node.id, + ...(searchKey && { searchKey }), + }) + } + /> +
    • + ) : null + )} +
    +
    + ) +} + +export default InfiniteTagList diff --git a/src/components/TagList/index.tsx b/src/components/TagList/index.tsx new file mode 100644 index 0000000000..e05e63110c --- /dev/null +++ b/src/components/TagList/index.tsx @@ -0,0 +1,5 @@ +import Infinite from './InfiniteTagList' + +export const TagList = { + Infinite, +} diff --git a/src/components/TagList/styles.module.css b/src/components/TagList/styles.module.css new file mode 100644 index 0000000000..bbc44fed00 --- /dev/null +++ b/src/components/TagList/styles.module.css @@ -0,0 +1,54 @@ +.tagList { + display: flex; + flex-wrap: wrap; + margin-top: var(--sp32); + + & .tagListItem { + @mixin border-bottom-grey-light; + + position: relative; + flex: 0 0 50%; + padding-bottom: var(--sp20); + margin-bottom: var(--sp20); + border-style: dashed; + + &:last-child { + flex-grow: 1; + } + } + + @media (--sm-down) { + & .tagListItem { + &:nth-child(2n + 1) { + padding-right: var(--sp16); + } + + &:last-child { + padding-right: 0; + + & a { + max-width: calc(50% - var(--sp16)); + } + } + } + } + + @media (--sm-up) { + & .tagListItem { + flex: 0 0 33.3333%; + + &:nth-child(3n + 1), + &:nth-child(3n + 2) { + padding-right: var(--sp16); + } + + &:last-child { + padding-right: 0; + + & a { + max-width: calc(33.3333% - var(--sp16)); + } + } + } + } +} diff --git a/src/components/index.tsx b/src/components/index.tsx index 5dfc6f01f4..6a28e147f3 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -74,6 +74,7 @@ export * from './Protected' export * from './ReCaptcha' export * from './Search' export * from './TagDigest' +export * from './TagList' export * from './TextSelectionPopover' export * from './Throw404' export * from './Transaction' diff --git a/src/views/Search/AggregateResults/Tags.tsx b/src/views/Search/AggregateResults/Tags.tsx index 07df228540..fe35990fa5 100644 --- a/src/views/Search/AggregateResults/Tags.tsx +++ b/src/views/Search/AggregateResults/Tags.tsx @@ -1,5 +1,4 @@ import { useEffect } from 'react' -import { FormattedMessage } from 'react-intl' import { LATER_SEARCH_RESULTS_LENGTH, @@ -8,9 +7,8 @@ import { import { analytics, mergeConnections } from '~/common/utils' import { EmptySearch, - InfiniteScroll, SpinnerBlock, - TagDigest, + TagList, Translate, usePublicQuery, useRoute, @@ -94,37 +92,14 @@ const AggregateTagResults = () => { return (
    - - } - > -
      - {edges.map( - ({ node, cursor }, i) => - node.__typename === 'Tag' && ( -
    • - - analytics.trackEvent('click_feed', { - type: 'search_tag', - contentType: 'tag', - location: i, - id: node.id, - searchKey: q, - }) - } - /> -
    • - ) - )} -
    -
    + trackingType="search_tag" + searchKey={q} + maxResults={MAX_SEARCH_RESULTS_LENGTH} + />
    ) } diff --git a/src/views/Search/AggregateResults/styles.module.css b/src/views/Search/AggregateResults/styles.module.css index bc4162c781..b664c825a3 100644 --- a/src/views/Search/AggregateResults/styles.module.css +++ b/src/views/Search/AggregateResults/styles.module.css @@ -32,61 +32,6 @@ padding: var(--sp16); } -.tagList { - display: flex; - flex-wrap: wrap; - margin-top: var(--sp32); - - & .tagListItem { - @mixin border-bottom-grey-light; - - position: relative; - flex: 0 0 50%; - padding-bottom: var(--sp20); - margin-bottom: var(--sp20); - border-style: dashed; - - &:last-child { - flex-grow: 1; - } - } - - @media (--sm-down) { - & .tagListItem { - &:nth-child(2n + 1) { - padding-right: var(--sp16); - } - - &:last-child { - padding-right: 0; - - & a { - max-width: calc(50% - var(--sp16)); - } - } - } - } - - @media (--sm-up) { - & .tagListItem { - flex: 0 0 33.3333%; - - &:nth-child(3n + 1), - &:nth-child(3n + 2) { - padding-right: var(--sp16); - } - - &:last-child { - padding-right: 0; - - & a { - max-width: calc(33.3333% - var(--sp16)); - } - } - } - } -} - .tabs { padding: 0 var(--sp16); margin: var(--sp32) 0 var(--sp16); diff --git a/src/views/Tags/Feed.tsx b/src/views/Tags/Feed.tsx index 40f6b55f50..7d286e01b2 100644 --- a/src/views/Tags/Feed.tsx +++ b/src/views/Tags/Feed.tsx @@ -3,17 +3,15 @@ import _get from 'lodash/get' import { analytics, mergeConnections } from '~/common/utils' import { EmptyTag, - InfiniteScroll, Layout, QueryError, SpinnerBlock, - TagDigest, + TagList, usePublicQuery, } from '~/components' import { AllTagsHottestQuery } from '~/gql/graphql' import { ALL_TAGS_HOTTEST } from './gql' -import styles from './styles.module.css' export type FeedType = 'recommended' | 'hottest' @@ -65,29 +63,12 @@ const Feed = ({ type }: Props) => { return ( - -
      - {edges.map(({ node: tag }, i) => ( -
    • - - analytics.trackEvent('click_feed', { - type: trackingType, - contentType: 'tag', - location: i, - id: tag.id, - }) - } - /> -
    • - ))} -
    -
    + trackingType={isRecommended ? 'all_tags_recommended' : 'all_tags'} + />
    ) } diff --git a/src/views/Tags/styles.module.css b/src/views/Tags/styles.module.css index 0c882e9a39..b40985fb44 100644 --- a/src/views/Tags/styles.module.css +++ b/src/views/Tags/styles.module.css @@ -5,57 +5,3 @@ margin-top: var(--sp32); } } - -.list { - display: flex; - flex-wrap: wrap; - - & .listItem { - @mixin border-bottom-grey-light; - - position: relative; - flex: 0 0 50%; - padding-bottom: var(--sp20); - margin-bottom: var(--sp20); - border-style: dashed; - - &:last-child { - flex-grow: 1; - } - } - - @media (--sm-down) { - & .listItem { - &:nth-child(2n + 1) { - padding-right: var(--sp16); - } - - &:last-child { - padding-right: 0; - - & a { - max-width: calc(50% - var(--sp16)); - } - } - } - } - - @media (--sm-up) { - & .listItem { - flex: 0 0 33.3333%; - - &:nth-child(3n + 1), - &:nth-child(3n + 2) { - padding-right: var(--sp16); - } - - &:last-child { - padding-right: 0; - - & a { - max-width: calc(33.3333% - var(--sp16)); - } - } - } - } -} From 940796735058f2a8d3957386ef70b5827120289b Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Wed, 27 Nov 2024 17:34:01 +0800 Subject: [PATCH 54/69] feat(TagDetail): Hide tag feed tabs when no hottest articles --- src/views/TagDetail/gql.ts | 3 +++ src/views/TagDetail/index.tsx | 3 ++- src/views/TagDetail/styles.module.css | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/views/TagDetail/gql.ts b/src/views/TagDetail/gql.ts index c37e5936fa..8f30da9c90 100644 --- a/src/views/TagDetail/gql.ts +++ b/src/views/TagDetail/gql.ts @@ -15,6 +15,9 @@ const tagFragment = gql` } ...ArticleCountTag ...TagBookmarkButtonTagPrivate + hottestArticles: articles(input: { first: 10, sortBy: byHottestDesc }) { + totalCount + } recommended(input: { first: 10 }) { edges { cursor diff --git a/src/views/TagDetail/index.tsx b/src/views/TagDetail/index.tsx index 1d7cc8c748..9b501072ec 100644 --- a/src/views/TagDetail/index.tsx +++ b/src/views/TagDetail/index.tsx @@ -63,6 +63,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { const isHottest = feedType === 'hottest' const isLatest = feedType === 'latest' const hasArticles = tag.numArticles > 0 + const hasHottestArticles = tag.hottestArticles.totalCount > 0 useEffect(() => { // backward compatible with `/tags/:globalId:` @@ -128,7 +129,7 @@ const TagDetail = ({ tag }: { tag: TagFragmentFragment }) => { - {hasArticles && ( + {hasArticles && hasHottestArticles && (
    Date: Wed, 27 Nov 2024 20:31:15 +0800 Subject: [PATCH 55/69] fix(TagDetail): Optimize tag detail query by reducing hottestArticles fetch size --- src/views/TagDetail/gql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/TagDetail/gql.ts b/src/views/TagDetail/gql.ts index 8f30da9c90..5898869933 100644 --- a/src/views/TagDetail/gql.ts +++ b/src/views/TagDetail/gql.ts @@ -15,7 +15,7 @@ const tagFragment = gql` } ...ArticleCountTag ...TagBookmarkButtonTagPrivate - hottestArticles: articles(input: { first: 10, sortBy: byHottestDesc }) { + hottestArticles: articles(input: { first: 0, sortBy: byHottestDesc }) { totalCount } recommended(input: { first: 10 }) { From d6ee834415670b2da1a2dfe6ac5cbfcf68eb23c2 Mon Sep 17 00:00:00 2001 From: Zeck Li <11781254+zeckli@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:54:27 +0800 Subject: [PATCH 56/69] feat(tracker): add the tracker for article reading timer --- src/common/utils/analytics.ts | 6 ++ src/components/Drawer/BaseDrawer.tsx | 1 + src/components/Hook/index.ts | 1 + src/components/Hook/useReadTimer.ts | 104 ++++++++++++++++++++++ src/views/ArticleDetail/Content/index.tsx | 3 + 5 files changed, 115 insertions(+) create mode 100644 src/components/Hook/useReadTimer.ts diff --git a/src/common/utils/analytics.ts b/src/common/utils/analytics.ts index bb4bfc4eb0..43db1a8f84 100644 --- a/src/common/utils/analytics.ts +++ b/src/common/utils/analytics.ts @@ -40,6 +40,7 @@ type EventArgs = | ['authenticate', AuthenticateProp] | ['billboard_exposure', BillboardExposureProp] | ['click_billboard', ClickBillboardProp] + | ['read_time', ReadTimeProp] /** * Event: Page View @@ -239,6 +240,11 @@ interface AuthenticateProp { trigger?: string } +interface ReadTimeProp { + articleId: string + time: number +} + // content type export type ContentType = | 'article' diff --git a/src/components/Drawer/BaseDrawer.tsx b/src/components/Drawer/BaseDrawer.tsx index 3fa67c593a..47eda8c754 100644 --- a/src/components/Drawer/BaseDrawer.tsx +++ b/src/components/Drawer/BaseDrawer.tsx @@ -82,6 +82,7 @@ export const BaseDrawer = ({ const containerClasses = classNames({ [styles.baseDrawerContainer]: true, + open: isOpen, // for read timer to identify the state }) const ref = useRef(null) diff --git a/src/components/Hook/index.ts b/src/components/Hook/index.ts index 828ad28fb8..0c40be308d 100644 --- a/src/components/Hook/index.ts +++ b/src/components/Hook/index.ts @@ -14,6 +14,7 @@ export * from './useJumpToComment' export * from './useMediaQuery' export * from './useNativeEventListener' export * from './useOutsideClick' +export * from './useReadTimer' export * from './useRoute' export * from './useStep' export * from './useTargetNetwork' diff --git a/src/components/Hook/useReadTimer.ts b/src/components/Hook/useReadTimer.ts new file mode 100644 index 0000000000..67cfd0389a --- /dev/null +++ b/src/components/Hook/useReadTimer.ts @@ -0,0 +1,104 @@ +import _throttle from 'lodash/throttle' +import { useRouter } from 'next/router' +import { useEffect, useRef } from 'react' + +import { analytics } from '~/common/utils' + +type Props = { + articleId: string + container?: React.RefObject +} + +export const useReadTimer = ({ articleId, container }: Props) => { + const router = useRouter() + + //in ms + const interval = 5000 + + const dummy = useRef(0) + const readTimer = useRef(0) + const lastScroll = useRef(Date.now() / 1000) + + useEffect(() => { + const handleScroll = _throttle(() => { + lastScroll.current = Date.now() / 1000 + }, 3000) + + const storeReadTime = () => { + if (articleId && readTimer?.current) + analytics.trackEvent('read_time', { + articleId, + time: readTimer.current, + }) + } + + window.addEventListener('scroll', handleScroll) + window.addEventListener('beforeunload', storeReadTime) + router.events.on('routeChangeStart', storeReadTime) + + return () => { + window.removeEventListener('scroll', handleScroll) + window.removeEventListener('beforeunload', storeReadTime) + router.events.off('routeChangeStart', storeReadTime) + } + }, []) + + // reading timer + useEffect(() => { + const timerId = setInterval( + (function heartbeat() { + const isReading = () => { + // tab hidden + if (document.hidden) { + return false + } + + // content not rendered + if (!container || !container.current) { + return false + } + + // idle for more than 3 minutes + if (Date.now() / 1000 - lastScroll.current > 60 * 3) { + return false + } + + // if overlay is shown + const overlaySelectors = ['reach-portal', '.tippy-popper'] + if (document.querySelector(overlaySelectors.join(','))) { + return false + } + + // if drawer is opened + if (document.querySelector('[id^="Drawer__"].open')) { + return false + } + + // if bottom is above center + const { bottom } = ( + container.current as unknown as Element + ).getBoundingClientRect() + + const isBottom = bottom <= window.innerHeight * 0.8 + return !isBottom + } + + // don't count the first time + if (dummy.current === 0) { + dummy.current = 1 + return heartbeat + } + + if (isReading()) { + readTimer.current = readTimer.current + interval + } + return heartbeat + })(), + interval + ) + + return () => { + clearInterval(timerId) + } + }, []) +} diff --git a/src/views/ArticleDetail/Content/index.tsx b/src/views/ArticleDetail/Content/index.tsx index 578f380447..ee3570620b 100644 --- a/src/views/ArticleDetail/Content/index.tsx +++ b/src/views/ArticleDetail/Content/index.tsx @@ -12,6 +12,7 @@ import { useRoute, ViewerContext, } from '~/components' +import { useReadTimer } from '~/components/Hook' import { ReadArticleMutation } from '~/gql/graphql' import styles from './styles.module.css' @@ -118,6 +119,8 @@ const Content = ({ } }, [lastScroll]) + useReadTimer({ articleId, container: contentContainer }) + return ( <>
    Date: Mon, 2 Dec 2024 14:52:55 +0800 Subject: [PATCH 57/69] fix(TagDigest): add word-break to tag names for better text wrapping PR-2411-1-1 --- src/components/TagDigest/Feed/styles.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/TagDigest/Feed/styles.module.css b/src/components/TagDigest/Feed/styles.module.css index 7ba1341211..2ec224d579 100644 --- a/src/components/TagDigest/Feed/styles.module.css +++ b/src/components/TagDigest/Feed/styles.module.css @@ -8,6 +8,7 @@ font-size: var(--text16); line-height: 1.5rem; /* 24px */ + word-break: break-all; } & .nums { From 27227cd16e370434042d03dc1d014563cdcf5171 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:59:09 +0800 Subject: [PATCH 58/69] fix(i18n): fix copy --- lang/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/en.json b/lang/en.json index 1ec6f90326..8511a9c5d0 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1214,7 +1214,7 @@ "defaultMessage": "Agree" }, "IUS82d": { - "defaultMessage": "Recommended Authors", + "defaultMessage": "Tag active authors", "description": "src/views/TagDetail/RecommendedAuthors/index.tsx" }, "IXycMo": { From e16337d3a915aa34a59a1f474f3d0890c43a0d89 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:21:18 +0800 Subject: [PATCH 59/69] fix(tag): add space separator between tag words ref: PR-2411-1-5 --- src/common/utils/text/tag.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utils/text/tag.ts b/src/common/utils/text/tag.ts index 1242d582dc..1d716d4816 100644 --- a/src/common/utils/text/tag.ts +++ b/src/common/utils/text/tag.ts @@ -25,7 +25,7 @@ const stripTagAllPunct = (content: string) => { return words[0] default: const [first, ...rest] = words - return `${first} ${rest.join('')}` + return `${first} ${rest.join(' ')}` } } From 7c84f7340846e4fc04303934cf2df1a5cd181015 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:44:54 +0800 Subject: [PATCH 60/69] fix(Tags): add reactive tag data fetching --- src/views/Tags/Feed.tsx | 26 ++++++++++++++++++++++++-- src/views/Tags/gql.ts | 11 +++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/views/Tags/Feed.tsx b/src/views/Tags/Feed.tsx index 7d286e01b2..82455aa2a0 100644 --- a/src/views/Tags/Feed.tsx +++ b/src/views/Tags/Feed.tsx @@ -1,4 +1,5 @@ import _get from 'lodash/get' +import { useEffect } from 'react' import { analytics, mergeConnections } from '~/common/utils' import { @@ -11,7 +12,7 @@ import { } from '~/components' import { AllTagsHottestQuery } from '~/gql/graphql' -import { ALL_TAGS_HOTTEST } from './gql' +import { ALL_TAGS_HOTTEST, TAG_REACTIVE_DATA } from './gql' export type FeedType = 'recommended' | 'hottest' @@ -26,7 +27,28 @@ const Feed = ({ type }: Props) => { const query = ALL_TAGS_HOTTEST - const { data, loading, error, fetchMore } = usePublicQuery(query) + const { data, loading, error, fetchMore, client } = + usePublicQuery(query) + + // fetch the latest tag data + const loadTagReactiveData = (publicData?: FeedQuery) => { + const publicEdges = publicData?.viewer?.recommendation.tags.edges || [] + const publicIds = publicEdges.map(({ node }) => node.id) + + if (publicIds.length <= 0) { + return + } + + client.query({ + query: TAG_REACTIVE_DATA, + fetchPolicy: 'network-only', + variables: { ids: publicIds }, + }) + } + + useEffect(() => { + loadTagReactiveData(data) + }, [data]) if (loading) { return diff --git a/src/views/Tags/gql.ts b/src/views/Tags/gql.ts index 23261429a9..94dbb2448a 100644 --- a/src/views/Tags/gql.ts +++ b/src/views/Tags/gql.ts @@ -27,3 +27,14 @@ export const ALL_TAGS_HOTTEST = gql` } ${TagDigest.Feed.fragments.tag} ` + +export const TAG_REACTIVE_DATA = gql` + query TagReactiveData($ids: [ID!]!) { + nodes(input: { ids: $ids }) { + id + ... on Tag { + numArticles + } + } + } +` From efa08149be0cf8dff038f61e63b980a95018d088 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:59:17 +0800 Subject: [PATCH 61/69] feat(TagDetail): enhance RecommendedAuthors with Slides component ref: PR-2411-1-7 --- src/components/Slides/index.tsx | 2 +- src/components/Slides/styles.module.css | 4 ++ .../TagDetail/RecommendedAuthors/index.tsx | 47 ++++++++++++++----- .../RecommendedAuthors/styles.module.css | 11 +++-- 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/components/Slides/index.tsx b/src/components/Slides/index.tsx index 541cafc620..e89084fe0f 100644 --- a/src/components/Slides/index.tsx +++ b/src/components/Slides/index.tsx @@ -12,7 +12,7 @@ interface SlidesProps { } interface SlideItemProps { - size?: 'sm' | 'md' + size?: 'xs' | 'sm' | 'md' onClick?: () => any } diff --git a/src/components/Slides/styles.module.css b/src/components/Slides/styles.module.css index d94027868e..e0797c3639 100644 --- a/src/components/Slides/styles.module.css +++ b/src/components/Slides/styles.module.css @@ -48,6 +48,10 @@ background: var(--color-grey-lighter); } +.sizeXs { + width: 15rem; +} + .sizeSm { width: 18rem; } diff --git a/src/views/TagDetail/RecommendedAuthors/index.tsx b/src/views/TagDetail/RecommendedAuthors/index.tsx index ecd430d9f5..b2df587273 100644 --- a/src/views/TagDetail/RecommendedAuthors/index.tsx +++ b/src/views/TagDetail/RecommendedAuthors/index.tsx @@ -5,7 +5,7 @@ import _random from 'lodash/random' import { FormattedMessage } from 'react-intl' import { analytics } from '~/common/utils' -import { List, usePublicQuery, UserDigest } from '~/components' +import { List, Slides, usePublicQuery, UserDigest } from '~/components' import { TagDetailRecommendedAuthorsQuery } from '~/gql/graphql' import { RECOMMENDED_AUTHORS } from './gql' @@ -32,6 +32,7 @@ const RecommendedAuthors: React.FC = ({ tagId, inSidebar, }) => { + const perColumn = 3 const { data } = usePublicQuery( RECOMMENDED_AUTHORS, { @@ -59,25 +60,49 @@ const RecommendedAuthors: React.FC = ({ [styles.inSidebar]: inSidebar, }) + if (inSidebar) { + return ( +
    + +
    + + {edges.map(({ node, cursor }, i) => ( + + trackRecommendedAuthors(i, node.id)} + hasFollow={false} + hasState={false} + /> + + ))} + +
    +
    + ) + } + return (
    - -
    - - {edges.map(({ node, cursor }, i) => ( - + }> + {_chunk(edges, perColumn).map((chunks, i) => ( + + {chunks.map(({ node, cursor }) => ( trackRecommendedAuthors(i, node.id)} hasFollow={false} hasState={false} /> - - ))} - -
    + ))} + + ))} +
    ) } diff --git a/src/views/TagDetail/RecommendedAuthors/styles.module.css b/src/views/TagDetail/RecommendedAuthors/styles.module.css index 705672e91e..8aa5c05b58 100644 --- a/src/views/TagDetail/RecommendedAuthors/styles.module.css +++ b/src/views/TagDetail/RecommendedAuthors/styles.module.css @@ -1,7 +1,12 @@ .recommendedAuthors { - padding-bottom: var(--sp24); - margin-top: var(--sp24); + padding-bottom: var(--sp20); + margin-top: var(--sp8); border-bottom: 1px dashed var(--color-grey-light); + + @media (--sm-up) { + padding-bottom: var(--sp24); + margin-top: var(--sp24); + } } .inSidebar { @@ -11,7 +16,7 @@ } .header { - margin-bottom: var(--sp18); + margin-bottom: var(--sp6); font-size: var(--text14); font-weight: var(--font-medium); line-height: 1.375rem; From 3f78e4f807f66628e9ee81071fdbaeee044744a8 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:26:06 +0800 Subject: [PATCH 62/69] fix(Tag): fix tails on letters cut off PR-2411-1-8 --- src/components/Tag/InlineTag/styles.module.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Tag/InlineTag/styles.module.css b/src/components/Tag/InlineTag/styles.module.css index 3ff6789424..b6b64f164e 100644 --- a/src/components/Tag/InlineTag/styles.module.css +++ b/src/components/Tag/InlineTag/styles.module.css @@ -15,9 +15,8 @@ & .name { @mixin line-clamp; - @mixin fix-cropped-letters; - line-height: inherit; + line-height: 1.01; color: var(--color-black); } From 7d5a781501edeab77c8ba930874c339fd253abce Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:46:56 +0800 Subject: [PATCH 63/69] fix(BookmarksTags): revise empty state PR-2411-1-9 --- lang/default.json | 3 +++ lang/en.json | 3 +++ lang/zh-Hans.json | 3 +++ lang/zh-Hant.json | 3 +++ src/components/Empty/EmptyTagBookmark.tsx | 15 +++++++++++++++ src/components/Empty/index.tsx | 1 + src/views/Me/Bookmarks/BookmarksTags.tsx | 4 ++-- 7 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/components/Empty/EmptyTagBookmark.tsx diff --git a/lang/default.json b/lang/default.json index 12c702c931..784c113eba 100644 --- a/lang/default.json +++ b/lang/default.json @@ -2544,6 +2544,9 @@ "iEJeQH": { "defaultMessage": "Liker ID" }, + "iIitRg": { + "defaultMessage": "Tag not bookmarked yet" + }, "iNZdM/": { "defaultMessage": "Switch to support creators with the Optimism network {br} Make support more convenient and affordable", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/en.json b/lang/en.json index 8511a9c5d0..2fcbe0300c 100644 --- a/lang/en.json +++ b/lang/en.json @@ -2544,6 +2544,9 @@ "iEJeQH": { "defaultMessage": "Liker ID" }, + "iIitRg": { + "defaultMessage": "Tag not bookmarked yet" + }, "iNZdM/": { "defaultMessage": "Switch to support creators with the Optimism network {br} Make support more convenient and affordable", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 3a9b30715c..82a99d37af 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -2544,6 +2544,9 @@ "iEJeQH": { "defaultMessage": "设置 Liker ID" }, + "iIitRg": { + "defaultMessage": "尚未收藏标签" + }, "iNZdM/": { "defaultMessage": "切换后即可支持创作者,采用 Optimism 网络{br}让支持更方便且费用低廉", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/lang/zh-Hant.json b/lang/zh-Hant.json index 6a769d5231..4d31476398 100644 --- a/lang/zh-Hant.json +++ b/lang/zh-Hant.json @@ -2544,6 +2544,9 @@ "iEJeQH": { "defaultMessage": "設置 Liker ID" }, + "iIitRg": { + "defaultMessage": "尚未收藏標籤" + }, "iNZdM/": { "defaultMessage": "切換後即可支持創作者,採用 Optimism 網路{br}讓支持更方便且費用低廉", "description": "src/components/Forms/PaymentForm/SwitchNetwork/index.tsx" diff --git a/src/components/Empty/EmptyTagBookmark.tsx b/src/components/Empty/EmptyTagBookmark.tsx new file mode 100644 index 0000000000..30c8930fdf --- /dev/null +++ b/src/components/Empty/EmptyTagBookmark.tsx @@ -0,0 +1,15 @@ +import { FormattedMessage } from 'react-intl' + +import { ReactComponent as IconSave } from '@/public/static/icons/24px/save.svg' +import { Empty, Icon } from '~/components' + +export const EmptyTagBookmark = () => ( + } + description={ + <> + + + } + /> +) diff --git a/src/components/Empty/index.tsx b/src/components/Empty/index.tsx index 5d1916b856..d684f0358b 100644 --- a/src/components/Empty/index.tsx +++ b/src/components/Empty/index.tsx @@ -13,6 +13,7 @@ export * from './EmptyResponse' export * from './EmptySearch' export * from './EmptyTag' export * from './EmptyTagArticles' +export * from './EmptyTagBookmark' export * from './EmptyTransaction' export * from './EmptyTransactionCurrency' export * from './EmptyTransactionSubscription' diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx index f5b36991c2..0c79f403ed 100644 --- a/src/views/Me/Bookmarks/BookmarksTags.tsx +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -4,7 +4,7 @@ import { FormattedMessage, useIntl } from 'react-intl' import { mergeConnections } from '~/common/utils' import { - EmptyBookmark, + EmptyTagBookmark, Head, InfiniteScroll, Layout, @@ -58,7 +58,7 @@ const BaseMeBookmarksTags = () => { const { edges, pageInfo } = data?.viewer?.following?.tags || {} if (!edges || edges.length <= 0 || !pageInfo) { - return + return } const loadMore = () => From 300c6956ab8e6419e20cde9f6aee639d4a3810f3 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 19:04:09 +0800 Subject: [PATCH 64/69] fix(Bookmarks): add followed tags check in BookmarksTags PR-2411-1-13 --- src/views/Me/Bookmarks/BookmarksTags.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx index 0c79f403ed..095d06b51f 100644 --- a/src/views/Me/Bookmarks/BookmarksTags.tsx +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -61,6 +61,14 @@ const BaseMeBookmarksTags = () => { return } + const hasFollowedTags = edges.some( + ({ node }) => node.__typename === 'Tag' && node.isFollower + ) + + if (!hasFollowedTags) { + return + } + const loadMore = () => fetchMore({ variables: { after: pageInfo.endCursor }, From c81f5d4ca9d17a40781dbf497134171b0f7b8c78 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Mon, 2 Dec 2024 20:09:27 +0800 Subject: [PATCH 65/69] fix(Bookmarks): ensure tag bookmarks update with refetch ref: PR-2411-1-13 --- src/components/Buttons/TagBookmark/Bookmark.tsx | 8 ++++++++ src/views/Me/Bookmarks/BookmarksTags.tsx | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/Buttons/TagBookmark/Bookmark.tsx b/src/components/Buttons/TagBookmark/Bookmark.tsx index 3e167b90e8..29273344a7 100644 --- a/src/components/Buttons/TagBookmark/Bookmark.tsx +++ b/src/components/Buttons/TagBookmark/Bookmark.tsx @@ -21,6 +21,9 @@ interface BookmarkProps { const Bookmark = ({ tag }: BookmarkProps) => { const viewer = useContext(ViewerContext) const intl = useIntl() + const { + ME_BOOKMARK_TAGS_FEED, + } = require('~/views/Me/Bookmarks/BookmarksTags') const [bookmark] = useMutation( TOGGLE_BOOKMARK_TAG, { @@ -35,6 +38,11 @@ const Bookmark = ({ tag }: BookmarkProps) => { }, } : undefined, + refetchQueries: [ + { + query: ME_BOOKMARK_TAGS_FEED, + }, + ], } ) diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx index 095d06b51f..9022976cb3 100644 --- a/src/views/Me/Bookmarks/BookmarksTags.tsx +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -17,7 +17,7 @@ import { MeBookmarkTagsFeedQuery } from '~/gql/graphql' import BookmarksTabs from './BookmarksTabs' -const ME_BOOKMARK_TAGS_FEED = gql` +export const ME_BOOKMARK_TAGS_FEED = gql` query MeBookmarkTagsFeed($after: String) { viewer { id From 4c53af1cc2a865cad996ba842b82d4bb58c95b9d Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Mon, 2 Dec 2024 22:25:03 +0700 Subject: [PATCH 66/69] feat(tag): revise tag queries --- src/common/enums/oauth.ts | 2 +- src/components/Context/Viewer/index.tsx | 3 -- src/components/GQL/updates/index.ts | 1 - .../GQL/updates/viewerFollowingTagCount.ts | 48 ------------------- .../TagDigest/Buttons/FollowButton/Follow.tsx | 4 -- .../Buttons/FollowButton/Unfollow.tsx | 4 -- src/views/Me/Bookmarks/BookmarksArticles.tsx | 6 +-- src/views/Me/Bookmarks/BookmarksTags.tsx | 31 ++++++------ 8 files changed, 19 insertions(+), 80 deletions(-) delete mode 100644 src/components/GQL/updates/viewerFollowingTagCount.ts diff --git a/src/common/enums/oauth.ts b/src/common/enums/oauth.ts index 5d9d60fc80..28594a3968 100644 --- a/src/common/enums/oauth.ts +++ b/src/common/enums/oauth.ts @@ -31,7 +31,7 @@ export const OAUTH_SCOPE_TREE = { zh_hans: '草稿', }, }, - subscriptions: { + bookmarkedArticles: { _t: { zh_hant: '收藏作品', zh_hans: '收藏作品', diff --git a/src/components/Context/Viewer/index.tsx b/src/components/Context/Viewer/index.tsx index 1108f0e46d..fcf44623b2 100644 --- a/src/components/Context/Viewer/index.tsx +++ b/src/components/Context/Viewer/index.tsx @@ -56,9 +56,6 @@ const ViewerFragments = { users(input: { first: 0 }) { totalCount } - tags(input: { first: 0 }) { - totalCount - } } followers(input: { first: 0 }) { totalCount diff --git a/src/components/GQL/updates/index.ts b/src/components/GQL/updates/index.ts index 5c66de9d90..69d12fde0e 100644 --- a/src/components/GQL/updates/index.ts +++ b/src/components/GQL/updates/index.ts @@ -16,7 +16,6 @@ export * from './userProfile' export * from './userWritings' export * from './viewerFolloweeCount' export * from './viewerFolloweeCount' -export * from './viewerFollowingTagCount' export * from './viewerUnreadFollowing' export * from './viewerUnreadNoticeCount' export * from './viewerWorksTabs' diff --git a/src/components/GQL/updates/viewerFollowingTagCount.ts b/src/components/GQL/updates/viewerFollowingTagCount.ts deleted file mode 100644 index 13851bfb78..0000000000 --- a/src/components/GQL/updates/viewerFollowingTagCount.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { DataProxy } from 'apollo-cache' -import gql from 'graphql-tag' - -import { ViewerFollowingTagCountQuery } from '~/gql/graphql' - -const VIEWER_FOLLOWING_TAG_COUNT = gql` - query ViewerFollowingTagCount { - viewer { - id - following { - tags(input: { first: 0 }) { - totalCount - } - } - } - } -` - -export const updateViewerFollowingTagCount = ({ - cache, - type, -}: { - cache: DataProxy - type: 'increment' | 'decrement' -}) => { - try { - const cacheData = cache.readQuery({ - query: VIEWER_FOLLOWING_TAG_COUNT, - }) - - if (!cacheData || !cacheData.viewer) { - return - } - - if (type === 'increment') { - cacheData.viewer.following.tags.totalCount++ - } else { - cacheData.viewer.following.tags.totalCount-- - } - - cache.writeQuery({ - query: VIEWER_FOLLOWING_TAG_COUNT, - data: cacheData, - }) - } catch (e) { - console.error(e) - } -} diff --git a/src/components/TagDigest/Buttons/FollowButton/Follow.tsx b/src/components/TagDigest/Buttons/FollowButton/Follow.tsx index d51319ec50..0e1203f461 100644 --- a/src/components/TagDigest/Buttons/FollowButton/Follow.tsx +++ b/src/components/TagDigest/Buttons/FollowButton/Follow.tsx @@ -7,7 +7,6 @@ import { UNIVERSAL_AUTH_TRIGGER, } from '~/common/enums' import { Button, TextIcon, useMutation, ViewerContext } from '~/components' -import { updateViewerFollowingTagCount } from '~/components/GQL' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { TagDigestFollowButtonPrivateFragment, @@ -33,9 +32,6 @@ const Follow = ({ tag }: Props) => { }, } : undefined, - update: (cache) => { - updateViewerFollowingTagCount({ cache, type: 'increment' }) - }, }) const onClick = () => { diff --git a/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx b/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx index a83e9509a1..41dc85a341 100644 --- a/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx +++ b/src/components/TagDigest/Buttons/FollowButton/Unfollow.tsx @@ -3,7 +3,6 @@ import { useState } from 'react' import { FormattedMessage } from 'react-intl' import { Button, TextIcon, useMutation } from '~/components' -import { updateViewerFollowingTagCount } from '~/components/GQL' import TOGGLE_BOOKMARK_TAG from '~/components/GQL/mutations/toggleBookmarkTag' import { TagDigestFollowButtonPrivateFragment, @@ -30,9 +29,6 @@ const Unfollow = ({ tag }: UnfollowTagProps) => { }, } : undefined, - update: (cache) => { - updateViewerFollowingTagCount({ cache, type: 'decrement' }) - }, } ) diff --git a/src/views/Me/Bookmarks/BookmarksArticles.tsx b/src/views/Me/Bookmarks/BookmarksArticles.tsx index aef610348b..8b7a3e2084 100644 --- a/src/views/Me/Bookmarks/BookmarksArticles.tsx +++ b/src/views/Me/Bookmarks/BookmarksArticles.tsx @@ -21,7 +21,7 @@ const ME_BOOKMARK_ARTICLES_FEED = gql` query MeBookmarkArticlesFeed($after: String) { viewer { id - subscriptions(input: { first: 10, after: $after }) { + bookmarkedArticles(input: { first: 10, after: $after }) { pageInfo { startCursor endCursor @@ -53,8 +53,8 @@ const BaseMeBookmarksArticles = () => { return } - const connectionPath = 'viewer.subscriptions' - const { edges, pageInfo } = data?.viewer?.subscriptions || {} + const connectionPath = 'viewer.bookmarkedArticles' + const { edges, pageInfo } = data?.viewer?.bookmarkedArticles || {} if (!edges || edges.length <= 0 || !pageInfo) { return diff --git a/src/views/Me/Bookmarks/BookmarksTags.tsx b/src/views/Me/Bookmarks/BookmarksTags.tsx index f5b36991c2..d63c23626b 100644 --- a/src/views/Me/Bookmarks/BookmarksTags.tsx +++ b/src/views/Me/Bookmarks/BookmarksTags.tsx @@ -1,5 +1,6 @@ import { useQuery } from '@apollo/react-hooks' import gql from 'graphql-tag' +import { Fragment } from 'react' import { FormattedMessage, useIntl } from 'react-intl' import { mergeConnections } from '~/common/utils' @@ -21,18 +22,16 @@ const ME_BOOKMARK_TAGS_FEED = gql` query MeBookmarkTagsFeed($after: String) { viewer { id - following { - tags(input: { first: 20, after: $after }) { - pageInfo { - startCursor - endCursor - hasNextPage - } - edges { - cursor - node { - ...TagDigestBookmarkTag - } + bookmarkedTags(input: { first: 20, after: $after }) { + pageInfo { + startCursor + endCursor + hasNextPage + } + edges { + cursor + node { + ...TagDigestBookmarkTag } } } @@ -54,8 +53,8 @@ const BaseMeBookmarksTags = () => { return } - const connectionPath = 'viewer.following.tags' - const { edges, pageInfo } = data?.viewer?.following?.tags || {} + const connectionPath = 'viewer.bookmarkedTags' + const { edges, pageInfo } = data?.viewer?.bookmarkedTags || {} if (!edges || edges.length <= 0 || !pageInfo) { return @@ -76,13 +75,13 @@ const BaseMeBookmarksTags = () => { {edges.map(({ node, cursor }) => ( - <> + {node.isFollower && ( )} - + ))} From abedc51eb0ae6e9c94440a8e7cdc8bf97b72e797 Mon Sep 17 00:00:00 2001 From: Kechicode <186776112+Kechicode@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:23:38 +0800 Subject: [PATCH 67/69] fix(TagDigest): delete Bookmark test --- .../TagDigest/Bookmark/Bookmark.test.tsx | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 src/components/TagDigest/Bookmark/Bookmark.test.tsx diff --git a/src/components/TagDigest/Bookmark/Bookmark.test.tsx b/src/components/TagDigest/Bookmark/Bookmark.test.tsx deleted file mode 100644 index de25ee0cf4..0000000000 --- a/src/components/TagDigest/Bookmark/Bookmark.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { MockedProvider } from '@apollo/react-testing' -import { render, screen } from '@testing-library/react' -import { IntlProvider } from 'react-intl' -import { describe, expect, it } from 'vitest' - -import { TEST_ID } from '~/common/enums' -import { TagDigest } from '~/components' -import { MOCK_TAG } from '~/stories/mocks' - -describe('', () => { - it('should render a TagDigest.Bookmark', () => { - render( - - - - - - ) - - const $bookmark = screen.getByTestId(TEST_ID.DIGEST_TAG_BOOKMARK) - expect($bookmark).toBeInTheDocument() - - const $name = screen.getByText(MOCK_TAG.content) - expect($name).toBeInTheDocument() - - const $bookmarkButton = screen.getByRole('button', { - name: 'Bookmark', - }) - expect($bookmarkButton).toBeInTheDocument() - }) - - it('should render a TagDigest.Bookmark with isFollower', () => { - render( - - - - - - ) - - const $bookmarkButton = screen.getByRole('button', { - name: 'Remove bookmark', - }) - expect($bookmarkButton).toBeInTheDocument() - }) -}) From ad84630b6d1a6db809dac33f326d3eb6d2298da0 Mon Sep 17 00:00:00 2001 From: gitwoz <177856586+gitwoz@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:34:48 +0700 Subject: [PATCH 68/69] feat(tag): use numArticles instead of articles.totalCount for tag article count --- src/components/GQL/fragments/tag.ts | 16 ------- .../GQL/queries/tagArticlesCount.ts | 15 ------ src/components/GQL/updates/index.ts | 1 - .../GQL/updates/tagArticlesCount.ts | 48 ------------------- src/components/Tag/ArticleTag/index.tsx | 1 - src/components/Tag/InlineTag/index.tsx | 1 - src/components/Tag/ListTag/index.tsx | 1 - src/components/Tag/PlainTag/index.tsx | 1 - src/components/TagDigest/Feed/index.tsx | 1 - src/views/Home/Sidebar/Tags/index.tsx | 5 +- src/views/TagDetail/ArticlesCount/index.tsx | 10 +--- src/views/TagDetail/gql.ts | 6 --- src/views/Tags/Feed.tsx | 26 +--------- src/views/Tags/gql.ts | 11 ----- 14 files changed, 6 insertions(+), 137 deletions(-) delete mode 100644 src/components/GQL/fragments/tag.ts delete mode 100644 src/components/GQL/queries/tagArticlesCount.ts delete mode 100644 src/components/GQL/updates/tagArticlesCount.ts diff --git a/src/components/GQL/fragments/tag.ts b/src/components/GQL/fragments/tag.ts deleted file mode 100644 index c01009e6f4..0000000000 --- a/src/components/GQL/fragments/tag.ts +++ /dev/null @@ -1,16 +0,0 @@ -import gql from 'graphql-tag' - -const fragments = { - articleCount: gql` - fragment ArticleCountTag on Tag { - id - numAuthors - numArticles - articles(input: { first: 0 }) { - totalCount - } - } - `, -} - -export default fragments diff --git a/src/components/GQL/queries/tagArticlesCount.ts b/src/components/GQL/queries/tagArticlesCount.ts deleted file mode 100644 index 563061da10..0000000000 --- a/src/components/GQL/queries/tagArticlesCount.ts +++ /dev/null @@ -1,15 +0,0 @@ -import gql from 'graphql-tag' - -import tagFragments from '../fragments/tag' - -export default gql` - query TagArticlesCount($id: ID!) { - node(input: { id: $id }) { - ... on Tag { - id - ...ArticleCountTag - } - } - } - ${tagFragments.articleCount} -` diff --git a/src/components/GQL/updates/index.ts b/src/components/GQL/updates/index.ts index 69d12fde0e..4aa90f493c 100644 --- a/src/components/GQL/updates/index.ts +++ b/src/components/GQL/updates/index.ts @@ -6,7 +6,6 @@ export * from './circleFollowers' export * from './commentDetail' export * from './draftAssets' export * from './momentDetail' -export * from './tagArticlesCount' export * from './userCollectionDetail' export * from './userCollections' export * from './userCollectionsArticles' diff --git a/src/components/GQL/updates/tagArticlesCount.ts b/src/components/GQL/updates/tagArticlesCount.ts deleted file mode 100644 index 46382f9c23..0000000000 --- a/src/components/GQL/updates/tagArticlesCount.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { DataProxy } from 'apollo-cache' -import _cloneDeep from 'lodash/cloneDeep' - -import TAG_ARTICLES_COUNT from '~/components/GQL/queries/tagArticlesCount' -import { TagArticlesCountQuery } from '~/gql/graphql' - -export const updateTagArticlesCount = ({ - cache, - id, - count = 1, - type, -}: { - cache: DataProxy - id: string - count?: number - type: 'increment' | 'decrement' -}) => { - try { - if (!id) { - return - } - - const variables = { id } - const cacheData = cache.readQuery({ - query: TAG_ARTICLES_COUNT, - variables, - }) - - const data = _cloneDeep(cacheData) - if (data?.node?.__typename !== 'Tag') { - return - } - - if (type === 'increment') { - data.node.articles.totalCount += count - } else { - data.node.articles.totalCount -= count - } - - cache.writeQuery({ - query: TAG_ARTICLES_COUNT, - variables, - data, - }) - } catch (e) { - console.error(e) - } -} diff --git a/src/components/Tag/ArticleTag/index.tsx b/src/components/Tag/ArticleTag/index.tsx index 4c4e7d95ce..d41a1342f0 100644 --- a/src/components/Tag/ArticleTag/index.tsx +++ b/src/components/Tag/ArticleTag/index.tsx @@ -59,7 +59,6 @@ ArticleTag.fragments = { id content numArticles - numAuthors } `, } diff --git a/src/components/Tag/InlineTag/index.tsx b/src/components/Tag/InlineTag/index.tsx index 8808fd9556..4137d574e6 100644 --- a/src/components/Tag/InlineTag/index.tsx +++ b/src/components/Tag/InlineTag/index.tsx @@ -75,7 +75,6 @@ InlineTag.fragments = { id content numArticles - numAuthors } `, } diff --git a/src/components/Tag/ListTag/index.tsx b/src/components/Tag/ListTag/index.tsx index 1fcacdfcdb..1f59a29742 100644 --- a/src/components/Tag/ListTag/index.tsx +++ b/src/components/Tag/ListTag/index.tsx @@ -81,7 +81,6 @@ ListTag.fragments = { id content numArticles - numAuthors } `, } diff --git a/src/components/Tag/PlainTag/index.tsx b/src/components/Tag/PlainTag/index.tsx index 0dc778eb1a..aa1ad9763b 100644 --- a/src/components/Tag/PlainTag/index.tsx +++ b/src/components/Tag/PlainTag/index.tsx @@ -52,7 +52,6 @@ PlainTag.fragments = { id content numArticles - numAuthors } `, } diff --git a/src/components/TagDigest/Feed/index.tsx b/src/components/TagDigest/Feed/index.tsx index ddfc6af9c3..104320423f 100644 --- a/src/components/TagDigest/Feed/index.tsx +++ b/src/components/TagDigest/Feed/index.tsx @@ -19,7 +19,6 @@ const fragments = { id content numArticles - numAuthors } `, } diff --git a/src/views/Home/Sidebar/Tags/index.tsx b/src/views/Home/Sidebar/Tags/index.tsx index 9656d0b804..645478cecf 100644 --- a/src/views/Home/Sidebar/Tags/index.tsx +++ b/src/views/Home/Sidebar/Tags/index.tsx @@ -5,7 +5,6 @@ import { useContext } from 'react' import { analytics } from '~/common/utils' import { List, - ListTag, QueryError, ShuffleButton, SpinnerBlock, @@ -33,14 +32,14 @@ const SIDEBAR_TAGS = gql` cursor node { id - ...DigestTag + ...TagDigestSidebarTag } } } } } } - ${ListTag.fragments.tag} + ${TagDigest.Sidebar.fragments.tag} ` const Tags = () => { diff --git a/src/views/TagDetail/ArticlesCount/index.tsx b/src/views/TagDetail/ArticlesCount/index.tsx index 1f5f45a83e..5b09252b06 100644 --- a/src/views/TagDetail/ArticlesCount/index.tsx +++ b/src/views/TagDetail/ArticlesCount/index.tsx @@ -1,17 +1,15 @@ import { FormattedMessage } from 'react-intl' import { numAbbr } from '~/common/utils' -import tagFragments from '~/components/GQL/fragments/tag' -import { ArticleCountTagFragment } from '~/gql/graphql' import styles from './styles.module.css' interface ArticlesCountProps { - tag: ArticleCountTagFragment + tag: { numArticles: number } } const ArticlesCount = ({ tag }: ArticlesCountProps) => { - const { totalCount } = tag.articles || { totalCount: 0 } + const totalCount = tag.numArticles return (
    @@ -30,8 +28,4 @@ const ArticlesCount = ({ tag }: ArticlesCountProps) => { ) } -ArticlesCount.fragments = { - tag: tagFragments.articleCount, -} - export default ArticlesCount diff --git a/src/views/TagDetail/gql.ts b/src/views/TagDetail/gql.ts index 5898869933..c58ccc9930 100644 --- a/src/views/TagDetail/gql.ts +++ b/src/views/TagDetail/gql.ts @@ -2,18 +2,14 @@ import gql from 'graphql-tag' import { TagBookmarkButton } from '~/components' -import ArticlesCount from './ArticlesCount' - const tagFragment = gql` fragment TagFragment on Tag { id content numArticles - numAuthors selectedArticles: articles(input: { first: 0 }) { totalCount } - ...ArticleCountTag ...TagBookmarkButtonTagPrivate hottestArticles: articles(input: { first: 0, sortBy: byHottestDesc }) { totalCount @@ -25,12 +21,10 @@ const tagFragment = gql` id content numArticles - numAuthors } } } } - ${ArticlesCount.fragments.tag} ${TagBookmarkButton.fragments.tag.private} ` diff --git a/src/views/Tags/Feed.tsx b/src/views/Tags/Feed.tsx index 82455aa2a0..7d286e01b2 100644 --- a/src/views/Tags/Feed.tsx +++ b/src/views/Tags/Feed.tsx @@ -1,5 +1,4 @@ import _get from 'lodash/get' -import { useEffect } from 'react' import { analytics, mergeConnections } from '~/common/utils' import { @@ -12,7 +11,7 @@ import { } from '~/components' import { AllTagsHottestQuery } from '~/gql/graphql' -import { ALL_TAGS_HOTTEST, TAG_REACTIVE_DATA } from './gql' +import { ALL_TAGS_HOTTEST } from './gql' export type FeedType = 'recommended' | 'hottest' @@ -27,28 +26,7 @@ const Feed = ({ type }: Props) => { const query = ALL_TAGS_HOTTEST - const { data, loading, error, fetchMore, client } = - usePublicQuery(query) - - // fetch the latest tag data - const loadTagReactiveData = (publicData?: FeedQuery) => { - const publicEdges = publicData?.viewer?.recommendation.tags.edges || [] - const publicIds = publicEdges.map(({ node }) => node.id) - - if (publicIds.length <= 0) { - return - } - - client.query({ - query: TAG_REACTIVE_DATA, - fetchPolicy: 'network-only', - variables: { ids: publicIds }, - }) - } - - useEffect(() => { - loadTagReactiveData(data) - }, [data]) + const { data, loading, error, fetchMore } = usePublicQuery(query) if (loading) { return diff --git a/src/views/Tags/gql.ts b/src/views/Tags/gql.ts index 94dbb2448a..23261429a9 100644 --- a/src/views/Tags/gql.ts +++ b/src/views/Tags/gql.ts @@ -27,14 +27,3 @@ export const ALL_TAGS_HOTTEST = gql` } ${TagDigest.Feed.fragments.tag} ` - -export const TAG_REACTIVE_DATA = gql` - query TagReactiveData($ids: [ID!]!) { - nodes(input: { ids: $ids }) { - id - ... on Tag { - numArticles - } - } - } -` From c99d2f159fb495dd466bc80db98c3b2ec31cc2c6 Mon Sep 17 00:00:00 2001 From: Woz <177856586+gitwoz@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:50:09 +0800 Subject: [PATCH 69/69] chore(release): v5.7.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 242319ed45..d0c625f838 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matters-web", - "version": "5.6.6", + "version": "5.7.0", "description": "codebase of Matters' website", "author": "Matters ", "engines": {