diff --git a/public/icons/static/article/unpin.svg b/public/icons/static/article/unpin.svg new file mode 100644 index 000000000..ddba75791 --- /dev/null +++ b/public/icons/static/article/unpin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Buttons/FancyPublishButton.tsx b/src/components/Buttons/FancyPublishButton.tsx new file mode 100755 index 000000000..0a7fb28eb --- /dev/null +++ b/src/components/Buttons/FancyPublishButton.tsx @@ -0,0 +1,71 @@ +/* + * + * PublishButton + * + */ + +import { memo, FC } from 'react' + +import { ICON_CMD } from '@/config' +import { buildLog } from '@/utils' + +import Tooltip from '@/components/Tooltip' +import { + Wrapper, + Label, + LabelIcon, + ActionLink, + Icon, +} from './styles/fancy_publish_button' + +/* eslint-disable-next-line */ +const log = buildLog('c:PublishButton:index') + +type TProps = { + label?: string + labelIconSrc?: string + onPublish?: () => void + onVote?: () => void + onImport?: () => void + onFAQ?: () => void +} + +const PublishButton: FC = ({ + label = '发布帖子 ', + labelIconSrc = `${ICON_CMD}/publish_pen.svg`, + onPublish = log, + onVote = log, + onImport = log, + onFAQ = log, +}) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default memo(PublishButton) diff --git a/src/components/Buttons/PublishButton.tsx b/src/components/Buttons/PublishButton.tsx index 69554adac..660c38de3 100755 --- a/src/components/Buttons/PublishButton.tsx +++ b/src/components/Buttons/PublishButton.tsx @@ -6,64 +6,77 @@ import { memo, FC } from 'react' -import { ICON_CMD } from '@/config' +import type { TThread } from '@/spec' + +import { THREAD } from '@/constant' +import { ICON } from '@/config' import { buildLog } from '@/utils' -import Tooltip from '@/components/Tooltip' -import { - Wrapper, - Label, - LabelIcon, - ActionLink, - Icon, -} from './styles/publish_button' +import DropdownButton from './DropdownButton' +import { Wrapper } from './styles/publish_button' /* eslint-disable-next-line */ const log = buildLog('c:PublishButton:index') +const getOptions = (thread) => { + switch (thread) { + case THREAD.JOB: { + return [ + { + key: 'publish', + icon: `${ICON}/edit/publish-write.svg`, + title: '我要招人', + desc: '发布后会第一次出现在相应版块首页。', + }, + { + key: 'link', + link: 'https://newpage', + icon: `${ICON}/article/report.svg`, + title: '发布须知', + desc: + '请确保你发布的内容符合社区的基本价值观和规范,否则会被限流或直接删除。', + }, + ] + } + default: { + return [ + { + key: 'publish', + icon: `${ICON}/edit/publish-write.svg`, + title: '发布帖子', + desc: '发布后会第一次出现在相应版块首页。', + }, + { + key: 'link', + link: 'https://newpage', + icon: `${ICON}/article/report.svg`, + title: '发布须知', + desc: + '请确保你发布的内容符合社区的基本价值观和规范,否则会被限流或直接删除。', + }, + ] + } + } +} + type TProps = { - label?: string - labelIconSrc?: string - onPublish?: () => void - onVote?: () => void - onImport?: () => void - onFAQ?: () => void + thread?: TThread + onCreate?: () => void } -const PublishButton: FC = ({ - label = '发布帖子 ', - labelIconSrc = `${ICON_CMD}/publish_pen.svg`, - onPublish = log, - onVote = log, - onImport = log, - onFAQ = log, -}) => { +const PublishButton: FC = ({ thread = THREAD.POST, onCreate }) => { return ( - - - - - - - - - - - - - - - - - - - - - + { + if (key === 'publish') onCreate() + }} + > + 发布帖子 + ) } diff --git a/src/components/Buttons/index.tsx b/src/components/Buttons/index.tsx index 911f53b88..5ba1f403b 100755 --- a/src/components/Buttons/index.tsx +++ b/src/components/Buttons/index.tsx @@ -1,6 +1,7 @@ export { default as Button } from './Button' export { default as ArrowButton } from './ArrowButton' export { default as ArrowLink } from './ArrowLink' +// export { default as FancyPublishButton } from './FancyPublishButton' export { default as PublishButton } from './PublishButton' export { default as OrButton } from './OrButton' export { default as DropdownButton } from './DropdownButton' diff --git a/src/components/Buttons/styles/fancy_publish_button.ts b/src/components/Buttons/styles/fancy_publish_button.ts new file mode 100755 index 000000000..a66151c3c --- /dev/null +++ b/src/components/Buttons/styles/fancy_publish_button.ts @@ -0,0 +1,116 @@ +import styled from 'styled-components' + +import Img from '@/Img' +import { css, theme } from '@/utils' + +// see example: https://codepen.io/mydearxym2/pen/qBEvvpo + +const commonHoverAffix = ` + content: ''; + position: absolute; + top: 0; + ${css.flex('align-center')}; + height: 100%; + transition: 0.25s linear; + z-index: 1; +` + +export const Wrapper = styled.div` + position: relative; + ${css.flex('align-both')}; + width: 100%; + max-width: 300px; + height: 32px; + background-color: #3680ad; /* 消失的时候背景色 */ + border-radius: 3px; + /* + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + */ + transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); + overflow: hidden; + + &:hover { + background-color: #22637e; /* #46627f; */ + /* + box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); + */ + } + + &:hover span { + opacity: 0; + z-index: -3; + } + &:hover:before { + opacity: 0.5; + transform: translateY(-100%); + } + &:hover:after { + opacity: 0.5; + transform: translateY(100%); + } + + &:before { + ${commonHoverAffix}; + width: 70%; + left: 0; + justify-content: flex-end; + background-color: #3e8ebf; + } + + &:after { + ${commonHoverAffix}; + width: 30%; + right: 0; + justify-content: flex-start; + background-color: #327faf; + } +` +export const Label = styled.span` + ${css.flex('align-center', 'justify-between')}; + padding-left: 16px; + padding-right: 16px; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + color: ${theme('button.fg')}; + font-family: 'Fira Mono', monospace; + font-size: 14px; + letter-spacing: 4px; + opacity: 1; + transition: opacity 0.25s; + z-index: 2; +` +export const LabelIcon = styled(Img)` + fill: ${theme('button.fg')}; + ${css.size(14)}; +` +export const ActionLink = styled.a` + position: relative; + ${css.flex('align-both')}; + /* width: 25%; */ + width: 45px; + /* height: 100%; */ + height: 32px; + color: whitesmoke; + font-size: 24px; + text-decoration: none; + transition: 0.25s; + + &:hover { + background: #18587a; + } +` +export const Icon = styled(Img)` + fill: ${theme('button.fg')}; + ${css.size(16)}; + + ${ActionLink}:hover & { + fill: ${theme('button.hoverBg')}; + cursor: pointer; + width: 18px; + height: 18px; + } + transition: all 0.25s; +` diff --git a/src/components/Buttons/styles/publish_button.ts b/src/components/Buttons/styles/publish_button.ts index a66151c3c..78ff5ddbc 100755 --- a/src/components/Buttons/styles/publish_button.ts +++ b/src/components/Buttons/styles/publish_button.ts @@ -1,116 +1,11 @@ import styled from 'styled-components' -import Img from '@/Img' -import { css, theme } from '@/utils' +// import Img from '@/Img' +// import { css, theme } from '@/utils' // see example: https://codepen.io/mydearxym2/pen/qBEvvpo -const commonHoverAffix = ` - content: ''; - position: absolute; - top: 0; - ${css.flex('align-center')}; - height: 100%; - transition: 0.25s linear; - z-index: 1; -` - export const Wrapper = styled.div` - position: relative; - ${css.flex('align-both')}; width: 100%; - max-width: 300px; - height: 32px; - background-color: #3680ad; /* 消失的时候背景色 */ - border-radius: 3px; - /* - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); - */ - transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); - overflow: hidden; - - &:hover { - background-color: #22637e; /* #46627f; */ - /* - box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); - */ - } - - &:hover span { - opacity: 0; - z-index: -3; - } - &:hover:before { - opacity: 0.5; - transform: translateY(-100%); - } - &:hover:after { - opacity: 0.5; - transform: translateY(100%); - } - - &:before { - ${commonHoverAffix}; - width: 70%; - left: 0; - justify-content: flex-end; - background-color: #3e8ebf; - } - - &:after { - ${commonHoverAffix}; - width: 30%; - right: 0; - justify-content: flex-start; - background-color: #327faf; - } -` -export const Label = styled.span` - ${css.flex('align-center', 'justify-between')}; - padding-left: 16px; - padding-right: 16px; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - color: ${theme('button.fg')}; - font-family: 'Fira Mono', monospace; - font-size: 14px; - letter-spacing: 4px; - opacity: 1; - transition: opacity 0.25s; - z-index: 2; -` -export const LabelIcon = styled(Img)` - fill: ${theme('button.fg')}; - ${css.size(14)}; -` -export const ActionLink = styled.a` - position: relative; - ${css.flex('align-both')}; - /* width: 25%; */ - width: 45px; - /* height: 100%; */ - height: 32px; - color: whitesmoke; - font-size: 24px; - text-decoration: none; - transition: 0.25s; - - &:hover { - background: #18587a; - } -` -export const Icon = styled(Img)` - fill: ${theme('button.fg')}; - ${css.size(16)}; - - ${ActionLink}:hover & { - fill: ${theme('button.hoverBg')}; - cursor: pointer; - width: 18px; - height: 18px; - } - transition: all 0.25s; ` +export const Wrapper2 = styled.div`` diff --git a/src/components/ContentBanner/styles/index.ts b/src/components/ContentBanner/styles/index.ts index 7c37a2c29..ffd2bde81 100755 --- a/src/components/ContentBanner/styles/index.ts +++ b/src/components/ContentBanner/styles/index.ts @@ -6,7 +6,7 @@ export const BaseBanner = styled.nav` ${css.flexColumn('justify-center')}; position: relative; - min-height: 140px; + min-height: 128px; background: ${theme('banner.bg')}; border-bottom: ${theme('banner.spliter')}; diff --git a/src/components/JobItem/ListView.js b/src/components/JobItem/ListView.js deleted file mode 100755 index 235f1816b..000000000 --- a/src/components/JobItem/ListView.js +++ /dev/null @@ -1,74 +0,0 @@ -import React from 'react' -import TimeAgo from 'timeago-react' - -import { ICON_CMD } from '@/config' -import { cutRest, parseDomain } from '@/utils' -import InlineTags from '@/components/InlineTags' -import DotDivider from '@/components/DotDivider' - -import { - Wrapper, - CompanyLogo, - TitleLink, - LinkIcon, - Salary, - Main, - TopHalf, - Brief, - Title, - SecondHalf, - TagsWrapper, - Extra, - CommentWrapper, - CommentIcon, - CommentNum, -} from './styles/list_view' -// import { Wrapper } from './styles' - -const ListView = ({ entry, onPreview }) => ( - - -
- - onPreview(entry)}> - - 【 {entry.company} 】{cutRest(entry.title, 45)} - - {entry.linkAddr && ( - - - - {parseDomain(entry.linkAddr)} - - - )} - - - - - - - - {entry.commentsCount} / {entry.views} - - - - - - - {entry.salary} - - {entry.author.nickname} - {entry.copyRight === 'original' ? ( -  发布于: - ) : ( -  搬运于: - )} - - - -
-
-) - -export default React.memo(ListView) diff --git a/src/components/JobItem/index.js b/src/components/JobItem/index.js index 8476dd169..dd2327756 100755 --- a/src/components/JobItem/index.js +++ b/src/components/JobItem/index.js @@ -12,7 +12,6 @@ import { buildLog } from '@/utils' import ArticleItemPrefixLabel from '@/components/ArticleItemPrefixLabel' import DigestView from './DigestView' -import ListView from './ListView' import { Wrapper } from './styles' import { getOpacity } from './helper' @@ -29,7 +28,7 @@ const JobItem = ({ community, }) => { const { - customization: { contentsLayout, contentDivider }, + customization: { contentDivider }, } = accountInfo return ( @@ -42,16 +41,12 @@ const JobItem = ({ accountInfo={accountInfo} topOffset="9px" /> - {contentsLayout === C11N.DIGEST ? ( - - ) : ( - - )} + ) } @@ -85,7 +80,6 @@ JobItem.propTypes = { accountInfo: T.shape({ isLogin: T.bool, customization: T.shape({ - contentsLayout: T.oneOf([C11N.DIGEST, C11N.LIST]), markViewed: T.bool, contentDivider: T.bool, displayDensity: T.oneOf(['20', '25', '30']), @@ -103,7 +97,6 @@ JobItem.defaultProps = { accountInfo: { isLogin: false, customization: T.shape({ - contentsLayout: C11N.DIGEST, contentDivider: false, markViewed: true, displayDensity: '20', diff --git a/src/components/JobItem/styles/list_view.ts b/src/components/JobItem/styles/list_view.ts deleted file mode 100755 index 10d524f5c..000000000 --- a/src/components/JobItem/styles/list_view.ts +++ /dev/null @@ -1,94 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' -import Img from '@/Img' - -export const Wrapper = styled.div` - ${css.flex()}; - - margin-bottom: 5px; - width: 100%; -` -export const Main = styled.div` - ${css.flexColumn()}; - flex-grow: 1; -` -export const TopHalf = styled.div` - ${css.flex()}; - line-height: 1; -` -export const SecondHalf = styled.div` - margin-left: 10px; - margin-top: -3px; -` -export const TagsWrapper = styled.div` - margin-top: 2px; -` -export const CompanyLogo = styled(Img)` - ${css.size(45)}; - border-radius: 5px; - opacity: ${theme('avatar.opacity')}; -` -export const Brief = styled.div` - ${css.flex('align-center')}; - flex-grow: 1; - margin-left: 10px; - margin-bottom: 10px; - color: ${theme('thread.articleTitle')}; -` - -export const Title = styled.div` - font-size: 1rem; - @media (max-width: 1450px) { - max-width: 500px; - } - @media (max-width: 1250px) { - max-width: 450px; - } - @media (max-width: 1100px) { - max-width: 350px; - } -` -export const TitleLink = styled.div` - position: relative; - font-size: 0.9rem; - margin-top: 2px; - color: ${theme('thread.articleLink')}; - margin-left: 10px; - opacity: 0.8; - text-decoration: underline; -` -export const LinkIcon = styled(Img)` - fill: ${theme('thread.articleLink')}; - position: absolute; - top: 6px; - left: -5px; - ${css.size(12)}; -` -export const Extra = styled.div` - ${css.flex('align-center')}; - opacity: 0.8; - transition: opacity 0.2s; - font-size: 0.9rem; - margin-top: 3px; - color: ${theme('thread.extraInfo')}; -` -export const Salary = styled.div` - color: ${theme('contrastFg')}; - margin-left: 7px; - font-weight: bold; - font-size: 0.9rem; -` -export const CommentWrapper = styled.div` - ${css.flex('align-center')}; - align-self: flex-start; -` -export const CommentIcon = styled(Img)` - fill: ${theme('thread.articleDigest')}; - ${css.size(14)}; - margin-right: 4px; -` -export const CommentNum = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 0.9rem; -` diff --git a/src/components/Navigator/BriefView.js b/src/components/Navigator/BriefView.tsx similarity index 84% rename from src/components/Navigator/BriefView.js rename to src/components/Navigator/BriefView.tsx index a5e8b7113..9ddcd5060 100755 --- a/src/components/Navigator/BriefView.js +++ b/src/components/Navigator/BriefView.tsx @@ -1,6 +1,6 @@ -import React from 'react' -import T from 'prop-types' +import { FC, memo } from 'react' +import type { TCommunity } from '@/spec' import { ICON_CMD } from '@/config' import Tooltip from '@/components/Tooltip' @@ -21,7 +21,11 @@ import MainEntries from './MainEntries/index' const CommunityLogoHolder = `${ICON_CMD}/community_logo_holder.svg` -const BriefView = ({ community }) => { +type TProps = { + community: TCommunity +} + +const BriefView: FC = ({ community }) => { return ( @@ -49,10 +53,4 @@ const BriefView = ({ community }) => { ) } -BriefView.propTypes = { - community: T.object.isRequired, -} - -BriefView.defaultProps = {} - -export default React.memo(BriefView) +export default memo(BriefView) diff --git a/src/components/Navigator/CardPopover.js b/src/components/Navigator/CardPopover.tsx similarity index 72% rename from src/components/Navigator/CardPopover.js rename to src/components/Navigator/CardPopover.tsx index 1be321240..cf280d012 100755 --- a/src/components/Navigator/CardPopover.js +++ b/src/components/Navigator/CardPopover.tsx @@ -1,6 +1,6 @@ -import React from 'react' +import { FC, memo } from 'react' -// import { ICON_CMD } from '@/config' +import type { TCommunity } from '@/spec' import CommunityStatesPad from '@/components/CommunityStatesPad' import { @@ -14,7 +14,11 @@ import { Footer, } from './styles/card_popover' -const CardPopover = ({ community }) => ( +type TProps = { + community: TCommunity +} + +const CardPopover: FC = ({ community }) => ( @@ -30,4 +34,4 @@ const CardPopover = ({ community }) => ( ) -export default React.memo(CardPopover) +export default memo(CardPopover) diff --git a/src/components/Navigator/DigestView.js b/src/components/Navigator/DigestView.tsx similarity index 59% rename from src/components/Navigator/DigestView.js rename to src/components/Navigator/DigestView.tsx index 2fdfd280e..179c8892b 100755 --- a/src/components/Navigator/DigestView.js +++ b/src/components/Navigator/DigestView.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { FC, memo } from 'react' import { METRIC } from '@/constant' import { @@ -13,6 +13,7 @@ import { } from './styles' import MainEntries from './MainEntries/index' +import { TC11NLayout } from '@/spec' const renderMainEntries = (metric) => { switch (metric) { @@ -26,15 +27,22 @@ const renderMainEntries = (metric) => { } } -const DigestView = ({ metric, showLogoText, isOnline }) => { +type TProps = { + metric: string + layout: TC11NLayout + showLogoText: boolean + isOnline: boolean +} + +const DigestView: FC = ({ metric, showLogoText, isOnline, layout }) => { return ( - + - {showLogoText && CoderPlanets} + {showLogoText && oderPlanets} - {showLogoText ? : } + {showLogoText ? : } {isOnline ? ( renderMainEntries(metric) @@ -45,4 +53,4 @@ const DigestView = ({ metric, showLogoText, isOnline }) => { ) } -export default React.memo(DigestView) +export default memo(DigestView) diff --git a/src/components/Navigator/MorePanel/DesktopView.js b/src/components/Navigator/MorePanel/DesktopView.tsx similarity index 94% rename from src/components/Navigator/MorePanel/DesktopView.js rename to src/components/Navigator/MorePanel/DesktopView.tsx index 3b63c4617..6129806c8 100644 --- a/src/components/Navigator/MorePanel/DesktopView.js +++ b/src/components/Navigator/MorePanel/DesktopView.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { FC, memo } from 'react' import Link from 'next/link' import { ICON } from '@/config' @@ -19,7 +19,7 @@ import { Wip, } from '../styles/more_panel' -const MoreContent = () => { +const MoreContent: FC = () => { return ( @@ -33,7 +33,7 @@ const MoreContent = () => { 贴纸/冰箱贴/各种奇奇怪怪。。 -
+
热门 @@ -89,4 +89,4 @@ const MoreContent = () => { ) } -export default React.memo(MoreContent) +export default memo(MoreContent) diff --git a/src/components/Navigator/MorePanel/Footer.js b/src/components/Navigator/MorePanel/Footer.js deleted file mode 100755 index 50be2b740..000000000 --- a/src/components/Navigator/MorePanel/Footer.js +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react' -import Link from 'next/link' - -import { ICON, GITHUB } from '@/config' -import { ROUTE } from '@/constant' - -// import DiscussLinker from '@/components/DiscussLinker' - -import { - Wrapper, - Entry, - Logo, - Main, - Title, - Desc, - Notice, -} from '../styles/more_panel/footer' - -const MoreContent = () => ( - - - -
- - 赞助与广告 -
- - 赞助社区,广告投放.. - 诚邀赞助 -
- - -
- - Open Source -
- - 本站全部代码开源在 Github 上,欢迎参与 -
-
-) - -export default React.memo(MoreContent) diff --git a/src/components/Navigator/MorePanel/Footer.tsx b/src/components/Navigator/MorePanel/Footer.tsx new file mode 100755 index 000000000..fdd31b4f2 --- /dev/null +++ b/src/components/Navigator/MorePanel/Footer.tsx @@ -0,0 +1,45 @@ +import { FC, memo } from 'react' +import Link from 'next/link' + +import { ICON, GITHUB } from '@/config' +import { ROUTE } from '@/constant' + +// import DiscussLinker from '@/components/DiscussLinker' + +import { + Wrapper, + Entry, + Logo, + Main, + Title, + Desc, + Notice, +} from '../styles/more_panel/footer' + +const MoreContent: FC = () => { + return ( + + + +
+ + 赞助与广告 +
+ + 赞助社区,广告投放.. + 诚邀赞助 +
+ + +
+ + Open Source +
+ + 本站全部代码开源在 Github 上,欢迎参与 +
+
+ ) +} + +export default memo(MoreContent) diff --git a/src/components/Navigator/MorePanel/MobileView.js b/src/components/Navigator/MorePanel/MobileView.tsx similarity index 80% rename from src/components/Navigator/MorePanel/MobileView.js rename to src/components/Navigator/MorePanel/MobileView.tsx index bb6542372..e80930834 100644 --- a/src/components/Navigator/MorePanel/MobileView.js +++ b/src/components/Navigator/MorePanel/MobileView.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { FC, memo } from 'react' import Link from 'next/link' import { ICON, ICON_CMD } from '@/config' @@ -16,20 +16,6 @@ import { } from '../styles/more_panel/mobile_view' const items = [ - // { - // icon: `${ICON_CMD}/header/more_shop.svg`, - // title: '小周边', - // desc: '贴纸/冰箱贴/各种奇奇怪怪', - // href: '', - // raw: 0, - // }, - // { - // icon: `${ICON}/discover.svg`, - // title: '发现', - // desc: '发现好玩的子社区', - // href: `/${ROUTE.DISCOVERY}`, - // raw: 1, - // }, { icon: `${ICON}/route/light.svg`, title: '作品集市', @@ -83,18 +69,19 @@ const items = [ icon: `${ICON_CMD}/header/more_snippets.svg`, title: '代码片段', desc: '各语言实用 Snippets,小技巧', + wip: true, href: '', raw: 3, }, ] -const MoreContent = () => { +const MoreContent: FC = () => { return ( - + {items.map((item, index) => ( - + @@ -110,4 +97,4 @@ const MoreContent = () => { ) } -export default React.memo(MoreContent) +export default memo(MoreContent) diff --git a/src/components/Navigator/MorePanel/index.js b/src/components/Navigator/MorePanel/index.tsx similarity index 51% rename from src/components/Navigator/MorePanel/index.js rename to src/components/Navigator/MorePanel/index.tsx index d296709f5..a0f3808b8 100755 --- a/src/components/Navigator/MorePanel/index.js +++ b/src/components/Navigator/MorePanel/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { Fragment, memo } from 'react' import { useDevice } from '@/hooks' @@ -8,11 +8,7 @@ import MobileView from './MobileView' const MoreContent = () => { const { isMobile } = useDevice() - return ( - <React.Fragment> - {!isMobile ? <DesktopView /> : <MobileView />} - </React.Fragment> - ) + return <Fragment>{!isMobile ? <DesktopView /> : <MobileView />}</Fragment> } -export default React.memo(MoreContent) +export default memo(MoreContent) diff --git a/src/components/Navigator/index.js b/src/components/Navigator/index.js deleted file mode 100755 index 051be794f..000000000 --- a/src/components/Navigator/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Navigator - * - */ - -import React from 'react' -import T from 'prop-types' -import { contains, values } from 'ramda' - -import { C11N, METRIC } from '@/constant' -import { buildLog } from '@/utils' - -import DigestView from './DigestView' -import BriefView from './BriefView' - -/* eslint-disable-next-line */ -const log = buildLog('c:Navigator:index') - -const Navigator = ({ curCommunity, layout, metric, isOnline }) => { - const showLogoText = !contains(metric, [ - METRIC.COMMUNITY, - METRIC.ARTICLE, - METRIC.ARTICLE_EDITOR, - ]) - - const onlyDigestView = contains(metric, [ - METRIC.ARTICLE, - METRIC.ARTICLE_EDITOR, - METRIC.USER, - METRIC.DISCOVERY, - ]) - - if (onlyDigestView) { - return ( - <DigestView - showLogoText={showLogoText} - isOnline={isOnline} - metric={metric} - /> - ) - } - - return ( - <React.Fragment> - {layout === C11N.BRIEF ? ( - <BriefView community={curCommunity} /> - ) : ( - <DigestView - showLogoText={showLogoText} - isOnline={isOnline} - metric={metric} - /> - )} - </React.Fragment> - ) -} - -Navigator.propTypes = { - curCommunity: T.object, - layout: T.oneOf([C11N.DIGEST, C11N.DIGEST_ROW, C11N.BRIEF]), - isOnline: T.bool, - metric: T.oneOf(values(METRIC)), -} - -Navigator.defaultProps = { - curCommunity: {}, - layout: C11N.DIGEST, - isOnline: true, - metric: METRIC.COMMUNITY, -} - -export default React.memo(Navigator) diff --git a/src/components/Navigator/index.tsx b/src/components/Navigator/index.tsx new file mode 100755 index 000000000..d69fbed7f --- /dev/null +++ b/src/components/Navigator/index.tsx @@ -0,0 +1,54 @@ +/* + * Navigator + */ + +import { FC, memo, Fragment } from 'react' +import { contains, values } from 'ramda' + +import type { TCommunity, TC11NLayout } from '@/spec' +import { C11N, METRIC, HCN } from '@/constant' +import { buildLog } from '@/utils' + +import DigestView from './DigestView' +// import BriefView from './BriefView' + +/* eslint-disable-next-line */ +const log = buildLog('c:Navigator:index') + +const shouldShowLogoText = ( + communityRaw: string, + metric: string, + layout: TC11NLayout, +): boolean => { + if (contains(metric, [METRIC.ARTICLE, METRIC.ARTICLE_EDITOR])) return false + if (communityRaw === HCN && layout === C11N.CLASSIC) return false + + return true +} + +type TProps = { + community: TCommunity + isOnline?: boolean + layout: TC11NLayout + metric?: string +} + +const Navigator: FC<TProps> = ({ + community, + layout, + metric = METRIC.COMMUNITY, + isOnline = true, +}) => { + const showLogoText = shouldShowLogoText(community.raw, metric, layout) + + return ( + <DigestView + layout={layout} + showLogoText={showLogoText} + isOnline={isOnline} + metric={metric} + /> + ) +} + +export default memo(Navigator) diff --git a/src/components/Navigator/styles/index.ts b/src/components/Navigator/styles/index.ts index 56c94e568..54fad5c7f 100755 --- a/src/components/Navigator/styles/index.ts +++ b/src/components/Navigator/styles/index.ts @@ -1,6 +1,7 @@ import styled from 'styled-components' -import type { TActive } from '@/spec' +import type { TActive, TC11NLayout } from '@/spec' +import { C11N } from '@/constant' import { animate, theme, css } from '@/utils' import CommunityFaceLogo from '@/components/CommunityFaceLogo' @@ -13,18 +14,17 @@ export const Breadcrumbs = styled.div` `}; ` export const Logo = styled(CommunityFaceLogo)` - height: 20px; - width: 20px; - margin-top: -1px; + ${css.size(16)}; ` -export const LogoLink = styled.a` +export const LogoLink = styled.a<{ layout: TC11NLayout }>` ${css.flex('align-center')}; - margin-right: 10px; + margin-right: ${({ layout }) => (layout === C11N.HOLY_GRAIL ? 0 : '10px')}; text-decoration: none; cursor: pointer; ` -export const LogoMargin = styled.div` - margin-right: 32px; +export const LogoMargin = styled.div<{ layout: TC11NLayout }>` + margin-right: ${({ layout }) => + layout === C11N.HOLY_GRAIL ? '42px' : '32px'}; ` export const LineDivider = styled.div` background-color: #139c9e; @@ -37,19 +37,13 @@ export const LineDivider = styled.div` animation: ${animate.blink} 1.2s linear infinite alternate; ` export const LogoText = styled.a` - color: ${theme('banner.desc')}; - /* font-weight: bold; */ + color: ${theme('header.fg')}; + font-weight: bold; + font-family: sans-serif; letter-spacing: 1px; - font-size: 14px; - margin-left: 10px; - margin-top: 4px; - - font-family: 'Audiowide', cursive; - /* font-family: 'Orbitron', sans-serif; */ - - &:hover { - color: ${theme('banner.desc')}; - } + font-size: 16px; + margin-left: 3px; + margin-top: 2px; ` export const UL = styled.ul` &:before { diff --git a/src/components/Navigator/styles/more_panel/index.ts b/src/components/Navigator/styles/more_panel/index.ts index a1877659e..6820a6236 100755 --- a/src/components/Navigator/styles/more_panel/index.ts +++ b/src/components/Navigator/styles/more_panel/index.ts @@ -3,7 +3,7 @@ import styled from 'styled-components' import { theme, css } from '@/utils' import Img from '@/Img' -export const Wrapper = styled.div<{ mobile: boolean }>` +export const Wrapper = styled.div<{ mobile?: boolean }>` ${css.flexColumn('align-center')}; width: ${({ mobile }) => (!mobile ? '455px' : '100%')}; min-height: 300px; @@ -14,7 +14,7 @@ export const BodyWrapper = styled.div` flex-wrap: wrap; margin-top: 25px; ` -export const Entry = styled.div<{ mobile: boolean }>` +export const Entry = styled.div<{ mobile?: boolean }>` ${css.flexColumn('align-start')}; width: ${({ mobile }) => (!mobile ? '225px' : '48%')}; height: 75px; @@ -28,7 +28,7 @@ export const Main = styled.a` ${css.flex('align-start')}; text-decoration: none; ` -export const Title = styled.div<{ offset: string }>` +export const Title = styled.div<{ offset?: string }>` ${css.flex('align-center')}; color: ${theme('thread.articleTitle')}; font-weight: bold; diff --git a/src/components/PagedContents/index.js b/src/components/PagedContents/index.js index 45c6e5aac..45e3f29dd 100755 --- a/src/components/PagedContents/index.js +++ b/src/components/PagedContents/index.js @@ -87,7 +87,6 @@ PagedContents.propTypes = { accountInfo: T.shape({ isLogin: T.bool, customization: T.shape({ - contentsLayout: T.oneOf([C11N.DIGEST, C11N.LIST]), markViewed: T.bool, displayDensity: T.oneOf(['20', '25', '30']), }), @@ -107,7 +106,6 @@ PagedContents.defaultProps = { accountInfo: { isLogin: false, customization: T.shape({ - contentsLayout: C11N.DIGEST, markViewed: true, displayDensity: '20', }), diff --git a/src/components/PostItem/index.tsx b/src/components/PostItem/index.tsx index 22e2ba852..ab9fb3513 100755 --- a/src/components/PostItem/index.tsx +++ b/src/components/PostItem/index.tsx @@ -7,7 +7,7 @@ import { FC, memo } from 'react' import type { TPost, TUser, TAccount } from '@/spec' -import { HCN, C11N } from '@/constant' +import { HCN } from '@/constant' import { buildLog } from '@/utils' import ArticleItemPrefixLabel from '@/components/ArticleItemPrefixLabel' @@ -41,7 +41,6 @@ const PostItem: FC<TProps> = ({ accountInfo = { isLogin: false, customization: { - contentsLayout: C11N.DIGEST, contentDivider: false, markViewed: true, displayDensity: '20', @@ -50,7 +49,7 @@ const PostItem: FC<TProps> = ({ }) => { // log('customization --> ', customization) const { - customization: { contentsLayout, contentDivider }, + customization: { contentDivider }, } = accountInfo return ( @@ -61,17 +60,13 @@ const PostItem: FC<TProps> = ({ divider={contentDivider} > <ArticleItemPrefixLabel entry={entry} accountInfo={accountInfo} /> - {contentsLayout === C11N.DIGEST ? ( - <DigestView - entry={entry} - community={community} - onPreview={onPreview} - onUserSelect={onUserSelect} - onAuthorSelect={onAuthorSelect} - /> - ) : ( - <ListView entry={entry} onPreview={onPreview} /> - )} + <DigestView + entry={entry} + community={community} + onPreview={onPreview} + onUserSelect={onUserSelect} + onAuthorSelect={onAuthorSelect} + /> </Wrapper> ) } diff --git a/src/components/PromotionList/styles/index.ts b/src/components/PromotionList/styles/index.ts index 0d52c6c9f..b0f4f06be 100755 --- a/src/components/PromotionList/styles/index.ts +++ b/src/components/PromotionList/styles/index.ts @@ -5,7 +5,6 @@ import { css, theme } from '@/utils' export const Wrapper = styled.div` margin-left: 20px; - margin-top: 30px; min-height: 150px; max-width: 180px; ` diff --git a/src/components/RepoItem/index.js b/src/components/RepoItem/index.js index c618ed9bb..f12d38813 100755 --- a/src/components/RepoItem/index.js +++ b/src/components/RepoItem/index.js @@ -56,7 +56,6 @@ RepoItem.propTypes = { accountInfo: T.shape({ isLogin: T.bool, customization: T.shape({ - contentsLayout: T.oneOf([C11N.DIGEST, C11N.LIST]), markViewed: T.bool, displayDensity: T.oneOf(['20', '25', '30']), }), @@ -70,7 +69,6 @@ RepoItem.defaultProps = { accountInfo: { isLogin: false, customization: T.shape({ - contentsLayout: C11N.DIGEST, markViewed: true, displayDensity: '20', }), diff --git a/src/components/SocialList/index.tsx b/src/components/SocialList/index.tsx new file mode 100755 index 000000000..591364a22 --- /dev/null +++ b/src/components/SocialList/index.tsx @@ -0,0 +1,60 @@ +import { FC, memo } from 'react' + +import type { TSIZE_SM } from '@/spec' +import { ICON_CMD } from '@/config' +import { SIZE } from '@/constant' + +import { Wrapper, SocialWrapper, Icon } from './styles' + +const defaultItems = [ + // { + // iconSrc: `${ICON_CMD}/navi/location.svg`, + // title: '成都', + // }, + { + iconSrc: `${ICON_CMD}/navi/space_in.svg`, + title: '官网', + }, + { + iconSrc: `${ICON_CMD}/github.svg`, + title: 'Github', + }, + { + iconSrc: `${ICON_CMD}/navi/twitter.svg`, + title: 'Twitter', + }, + { + iconSrc: `${ICON_CMD}/drink/zhihu.svg`, + title: '知乎', + }, +] + +type TProps = { + size?: TSIZE_SM + testid?: string + items?: { + iconSrc: string + title: string + }[] +} + +const SocialList: FC<TProps> = ({ + size = SIZE.SMALL, + testid = 'social-list', + items = defaultItems, +}) => { + return ( + <Wrapper testid={testid}> + {items.map((item) => ( + <SocialWrapper key={item.title}> + <Icon size={size} src={item.iconSrc} /> + {/* <Title size={size}> + {item.title} + */} + + ))} + + ) +} + +export default memo(SocialList) diff --git a/src/components/SocialList/styles/index.ts b/src/components/SocialList/styles/index.ts new file mode 100755 index 000000000..feee42057 --- /dev/null +++ b/src/components/SocialList/styles/index.ts @@ -0,0 +1,46 @@ +import styled from 'styled-components' + +import type { TTestable, TSIZE_SM } from '@/spec' +import { theme, css } from '@/utils' + +import Img from '@/Img' + +export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ + 'data-test-id': testid, +}))` + display: flex; + flex-wrap: wrap; +` +export const SocialWrapper = styled.div` + ${css.flex('align-center')}; + color: ${theme('banner.desc')}; + font-size: 12px; + /* border: 1px solid; */ + /* border-color: ${theme('banner.desc')}; */ + border-radius: 5px; + margin-right: 8px; + margin-bottom: 0; + width: auto; + text-decoration: underline; + + &:hover { + color: ${theme('banner.active')}; + cursor: pointer; + } +` +export const Icon = styled(Img)<{ size: TSIZE_SM }>` + fill: ${theme('banner.desc')}; + border-radius: 50%; + width: ${({ size }) => (size === 'small' ? '13px;' : '17px')}; + height: ${({ size }) => (size === 'small' ? '13px;' : '17px')}; + padding: 0; + margin-right: ${({ size }) => (size === 'small' ? '2px' : '10px')}; + display: block; + + ${SocialWrapper}:hover & { + fill: ${theme('banner.active')}; + } +` +export const Title = styled.div<{ size: string }>` + font-size: ${({ size }) => (size === 'small' ? '12px;' : '14px')}; +` diff --git a/src/components/SocialList/tests/index.test.ts b/src/components/SocialList/tests/index.test.ts new file mode 100755 index 000000000..528423bc2 --- /dev/null +++ b/src/components/SocialList/tests/index.test.ts @@ -0,0 +1,10 @@ +// import React from 'react' +// import { shallow } from 'enzyme' + +// import SocialList from '../index' + +describe('TODO ', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(true) + }) +}) diff --git a/src/components/Switcher/Tabs/CardView.tsx b/src/components/Switcher/Tabs/CardView.tsx deleted file mode 100644 index 214857ea9..000000000 --- a/src/components/Switcher/Tabs/CardView.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Tabs - * - */ - -import { FC, useRef, useState, useCallback, memo } from 'react' - -import type { TSIZE_SM, TTabItem } from '@/spec' -import { buildLog, isString } from '@/utils' -import { SIZE } from '@/constant' - -import TabItem from './TabItem' -import { Wrapper, Nav } from '../styles/tabs' - -/* eslint-disable-next-line */ -const log = buildLog('c:Tabs:index') - -// const defaultItems2 = ['帖子', '开源项目', 'Cheatsheet', '工作机会', '职场'] -const temItems = [ - { - title: '帖子', - raw: 'posts', - localIcon: 'settings', - }, -] - -type TProps = { - items?: TTabItem[] - onChange: () => void - activeKey?: string - size: TSIZE_SM - slipHeight: '1px' | '2px' -} - -const Tabs: FC = ({ - size = SIZE.MEDIUM, - onChange = log, - items = temItems, - activeKey = '', -}) => { - const [tabWidthList, setTabWidthList] = useState([]) - - const navRef = useRef(null) - - // set slipbar with for current nav item - // 为下面的滑动条设置当前 TabItem 的宽度 - const handleNaviItemWith = useCallback( - (index, width) => { - tabWidthList[index] = width - setTabWidthList(tabWidthList) - }, - [tabWidthList], - ) - - const handleItemClick = useCallback( - (index) => { - const item = items[index] - - onChange(isString(item) ? item : item.raw || item.title) - }, - [onChange, items], - ) - - return ( - - - - ) -} - -export default memo(Tabs) diff --git a/src/components/Switcher/Tabs/DesktopView.tsx b/src/components/Switcher/Tabs/DesktopView.tsx index cff20978d..9bb47f36f 100644 --- a/src/components/Switcher/Tabs/DesktopView.tsx +++ b/src/components/Switcher/Tabs/DesktopView.tsx @@ -7,9 +7,9 @@ import { FC, useEffect, useRef, useState, useCallback, memo } from 'react' import { isEmpty, findIndex } from 'ramda' -import type { TSIZE_SM, TTabItem } from '@/spec' +import type { TSIZE_SM, TTabItem, TC11NLayout } from '@/spec' import { useDevice } from '@/hooks' -import { SIZE } from '@/constant' +import { SIZE, C11N } from '@/constant' import { buildLog, isString } from '@/utils' import TabItem from './TabItem' @@ -51,6 +51,7 @@ const getDefaultActiveTabIndex = ( type TProps = { items?: TTabItem[] + layout?: TC11NLayout onChange: () => void activeKey?: string size: TSIZE_SM @@ -61,6 +62,7 @@ const Tabs: FC = ({ size = SIZE.MEDIUM, onChange = log, items = temItems, + layout = C11N.CLASSIC, activeKey = '', slipHeight = '2px', }) => { @@ -119,6 +121,7 @@ const Tabs: FC = ({ = ({ mobileView = false, modelineView = false, - cardView = false, + holyGrailView = false, wrapMode = false, activeKey, item, @@ -88,7 +88,7 @@ const TabItem: FC = ({ ref={ref} mobileView={mobileView} modelineView={modelineView} - cardView={cardView} + holyGrailView={holyGrailView} wrapMode={wrapMode} size={size} onClick={handleWrapperClick} diff --git a/src/components/Switcher/Tabs/index.tsx b/src/components/Switcher/Tabs/index.tsx index 319de4f17..8c31a0e5d 100644 --- a/src/components/Switcher/Tabs/index.tsx +++ b/src/components/Switcher/Tabs/index.tsx @@ -13,7 +13,6 @@ import { buildLog } from '@/utils' import DesktopView from './DesktopView' import MobileView from './MobileView/index' import ModelineView from './ModelineView' -import CardView from './CardView' import DrawerView from './DrawerView' /* eslint-disable-next-line */ @@ -36,10 +35,6 @@ const Tabs = (props) => { return } - case VIEW.COMMUNITY_CARD: { - return - } - case VIEW.DRAWER: { return } diff --git a/src/components/Switcher/styles/metric/tabs.ts b/src/components/Switcher/styles/metric/tabs.ts index ad4b5803e..080fd82cb 100644 --- a/src/components/Switcher/styles/metric/tabs.ts +++ b/src/components/Switcher/styles/metric/tabs.ts @@ -1,7 +1,12 @@ import { SIZE } from '@/constant' -export const getSlipMargin = (size: string, mobileView: boolean): number => { +export const getSlipMargin = ( + size: string, + mobileView: boolean, + holyGrailView = false, +): number => { if (mobileView) return 5 + if (holyGrailView) return 15 switch (size) { case SIZE.SMALL: { @@ -16,10 +21,10 @@ export const getSlipMargin = (size: string, mobileView: boolean): number => { export const getMarginRight = ( size: string, mobileView: boolean, - cardView: boolean, + holyGrailView: boolean, ): string => { if (mobileView) return '5px' - if (cardView) return '0' + if (holyGrailView) return '15px' switch (size) { case SIZE.SMALL: { @@ -33,12 +38,12 @@ export const getMarginRight = ( export const getPadding = ( size: string, - cardView: boolean, + holyGrailView: boolean, mobileView: boolean, wrapMode: boolean, modelineView: boolean, ): string => { - if (cardView) return '2px' + if (holyGrailView) return '12px 10px' if (modelineView) { return '6px 10px' @@ -62,10 +67,10 @@ export const getPadding = ( } export const getMarginBottom = ( - cardView: boolean, + holyGrailView: boolean, wrapMode: boolean, ): string => { - if (cardView) return '8px' + if (holyGrailView) return '0' if (wrapMode) return '4px' return '0' diff --git a/src/components/Switcher/styles/tabs/index.ts b/src/components/Switcher/styles/tabs/index.ts index 24d893df8..917d9c8dc 100755 --- a/src/components/Switcher/styles/tabs/index.ts +++ b/src/components/Switcher/styles/tabs/index.ts @@ -20,7 +20,7 @@ export const Wrapper = styled.nav.attrs(({ testid }: TTestable) => ({ export const Nav = styled.nav` position: relative; ${css.flex('align-center')}; - flex-flow: row wrap; + flex-flow: nowrap; margin: 0 auto; padding: 0; ` diff --git a/src/components/Switcher/styles/tabs/tab_item.ts b/src/components/Switcher/styles/tabs/tab_item.ts index 43d64d4a7..9f3f373b3 100644 --- a/src/components/Switcher/styles/tabs/tab_item.ts +++ b/src/components/Switcher/styles/tabs/tab_item.ts @@ -8,7 +8,7 @@ import { getMarginRight, getPadding, getMarginBottom } from '../metric/tabs' type TTab = { size: string mobileView: boolean - cardView: boolean + holyGrailView: boolean wrapMode: boolean modelineView: boolean } & TActive @@ -19,28 +19,18 @@ export const Wrapper = styled.div` position: relative; height: 100%; z-index: 1; - margin-right: ${({ size, mobileView, cardView }) => - getMarginRight(size, mobileView, cardView)}; - padding: ${({ size, cardView, mobileView, wrapMode, modelineView }) => - getPadding(size, cardView, mobileView, wrapMode, modelineView)}; + margin-right: ${({ size, mobileView, holyGrailView }) => + getMarginRight(size, mobileView, holyGrailView)}; + padding: ${({ size, holyGrailView, mobileView, wrapMode, modelineView }) => + getPadding(size, holyGrailView, mobileView, wrapMode, modelineView)}; text-align: center; - min-width: ${({ cardView }) => (!cardView ? 'auto' : '33%')}; + min-width: auto; cursor: pointer; - margin-bottom: ${({ cardView, wrapMode }) => - getMarginBottom(cardView, wrapMode)}; + margin-bottom: ${({ holyGrailView, wrapMode }) => + getMarginBottom(holyGrailView, wrapMode)}; - background: ${({ cardView, active }) => - cardView && active ? '#114758' : ''}; - border-left: ${({ cardView, active }) => - cardView && active ? '1px solid' : ''}; - /* same with slipbar */ - border-left-color: ${({ cardView, active }) => - cardView && active ? '#327faf' : ''}; - border-top-right-radius: ${({ cardView, active }) => - cardView && active ? '8px' : ''}; - border-bottom-right-radius: ${({ cardView, active }) => - cardView && active ? '8px' : ''}; + /* background: ${({ active }) => (active ? '#114758' : '')}; */ ${css.media.mobile` margin-right: ${() => getMarginRight('', true, false)}; diff --git a/src/components/TabBar/DesktopView/NormalView.tsx b/src/components/TabBar/DesktopView/NormalView.tsx index 75c3d3bb4..8fff9f52f 100755 --- a/src/components/TabBar/DesktopView/NormalView.tsx +++ b/src/components/TabBar/DesktopView/NormalView.tsx @@ -10,7 +10,7 @@ const getLocalIcon = (item) => { return item.localIcon ? item.localIcon : item.raw } -const NormalView = ({ source, active, onChange, size }) => { +const NormalView = ({ layout, source, active, onChange, size }) => { const items = source.map((item) => ({ ...item, localIcon: getLocalIcon(item), @@ -18,6 +18,7 @@ const NormalView = ({ source, active, onChange, size }) => { return ( void @@ -30,7 +29,7 @@ const TabBar: FC = ({ source, active = THREAD.POST, onChange = log, - layout = C11N.DIGEST, + layout = C11N.CLASSIC, communityRaw = HCN, size = SIZE.MEDIUM, }) => { @@ -39,16 +38,13 @@ const TabBar: FC = ({ return (
- {layout === C11N.BRIEF ? ( - - ) : ( - - )} +
) } diff --git a/src/components/TabBar/index.tsx b/src/components/TabBar/index.tsx index 639f529f8..dd67645e3 100755 --- a/src/components/TabBar/index.tsx +++ b/src/components/TabBar/index.tsx @@ -15,11 +15,12 @@ import MobileView from './MobileView' const log = buildLog('c:TabBar:index') const TabBar = (props) => { - const { view } = props + // const { view } = props const { isMobile } = useDevice() const curMedia = isMobile ? VIEW.MOBILE : VIEW.DESKTOP - const curView = view === 'auto' ? curMedia : view + // const curView = view && view === 'auto' ? curMedia : view + const curView = curMedia switch (curView) { case VIEW.DESKTOP: { diff --git a/src/containers/content/CommunityContent/SubscribedList/ExpandButton.tsx b/src/containers/content/CommunityContent/SubscribedList/ExpandButton.tsx new file mode 100755 index 000000000..8fb17ef9a --- /dev/null +++ b/src/containers/content/CommunityContent/SubscribedList/ExpandButton.tsx @@ -0,0 +1,35 @@ +/* + * + * Expand Button + * + */ + +import { FC, memo } from 'react' + +import { ICON } from '@/config' +import { buildLog } from '@/utils' + +import { + Wrapper, + ArrowIcon, + Text, +} from '../styles/subscribed_list/expand_button' + +/* eslint-disable-next-line */ +const log = buildLog('C:CommunityContent') + +type TProps = { + isExpanded?: boolean + onClick?: () => void +} + +const ExpandButton: FC = ({ isExpanded = false, onClick }) => { + return ( + + + {isExpanded ? 展开 : 收起} + + ) +} + +export default memo(ExpandButton) diff --git a/src/containers/content/CommunityContent/SubscribedList/ItemMenu.tsx b/src/containers/content/CommunityContent/SubscribedList/ItemMenu.tsx new file mode 100644 index 000000000..1537bc5fd --- /dev/null +++ b/src/containers/content/CommunityContent/SubscribedList/ItemMenu.tsx @@ -0,0 +1,37 @@ +/* + * + * CommunityContent + * + */ + +import { FC, memo } from 'react' + +import type { TCommunity } from '@/spec' +import { ICON } from '@/config' +import { buildLog } from '@/utils' + +import { Wrapper, Item, Icon, Title } from '../styles/subscribed_list/item_menu' + +/* eslint-disable-next-line */ +const log = buildLog('C:CommunityContent') + +type TProps = { + community: TCommunity +} + +const ItemMenu: FC = ({ community }) => { + return ( + + + + 置顶 + + + + 取消关注 + + + ) +} + +export default memo(ItemMenu) diff --git a/src/containers/content/CommunityContent/SubscribedList/index.tsx b/src/containers/content/CommunityContent/SubscribedList/index.tsx new file mode 100644 index 000000000..3f1e314aa --- /dev/null +++ b/src/containers/content/CommunityContent/SubscribedList/index.tsx @@ -0,0 +1,76 @@ +/* + * User subscribed communities list + */ + +import { FC, memo, Fragment, useState } from 'react' + +import type { TCommunity } from '@/spec' +import { ICON } from '@/config' +import { buildLog } from '@/utils' + +import DotDivider from '@/components/DotDivider' +import Tooltip from '@/components/Tooltip' +import { Br, SpaceGrow } from '@/components/Common' + +import ItemMenu from './ItemMenu' +import ExpandButton from './ExpandButton' + +import { + Wrapper, + Item, + Logo, + Title, + HeadTitle, + HeadNum, + Option, + OptionIcon, +} from '../styles/subscribed_list' + +/* eslint-disable-next-line */ +const log = buildLog('C:CommunityContent') + +type TProps = { + communities: TCommunity[] +} + +const SubscribedList: FC = ({ communities }) => { + const [expand, setExpand] = useState(false) + + return ( + +
+ + 我的关注 + {communities.length} + +
+ + + 首页 + + {communities.slice(0, 15).map((community) => ( + + + + {community.title} + + } + placement="bottom" + hideOnClick={false} + trigger="click" + noPadding + > + + + + + ))} + setExpand(!expand)} /> +
+ ) +} + +export default memo(SubscribedList) diff --git a/src/containers/content/CommunityContent/index.tsx b/src/containers/content/CommunityContent/index.tsx index c5d4ea016..35b8b1f2a 100755 --- a/src/containers/content/CommunityContent/index.tsx +++ b/src/containers/content/CommunityContent/index.tsx @@ -10,13 +10,17 @@ import { ROUTE, C11N } from '@/constant' import { useDevice } from '@/hooks' import { pluggedIn, buildLog } from '@/utils' +import CommunityDigest from '@/containers/digest/CommunityDigest' +import ThreadSidebar from '@/containers/thread/ThreadSidebar' import PostsThread from '@/containers//thread/PostsThread' import BlogsThread from '@/containers//thread/BlogsThread' import ReposThread from '@/containers/thread/ReposThread' import JobsThread from '@/containers/thread/JobsThread' import UsersThread from '@/containers/thread/UsersThread' +import SubscribedList from './SubscribedList' import type { TStore } from './store' + import { Wrapper, InnerWrapper } from './styles' import { useInit } from './logic' @@ -56,14 +60,23 @@ const CommunityContentContainer: FC = ({ communityContent: store }) => { accountInfo: { customization: { bannerLayout }, }, + subscribedCommunitiesData, } = store - const isCardView = !isMobile && bannerLayout === C11N.DIGEST_ROW + const isClassicLayout = !isMobile && bannerLayout === C11N.CLASSIC + const isHolyGrailLayout = !isMobile && bannerLayout === C11N.HOLY_GRAIL + + // console.log('subscribedCommunitiesData ->> ', subscribedCommunitiesData) return ( - - + + {isClassicLayout && } + + {isHolyGrailLayout && ( + + )} + {isHolyGrailLayout && } ) diff --git a/src/containers/content/CommunityContent/store.ts b/src/containers/content/CommunityContent/store.ts index 38ef3fe0a..926aa97d0 100755 --- a/src/containers/content/CommunityContent/store.ts +++ b/src/containers/content/CommunityContent/store.ts @@ -5,8 +5,8 @@ import { types as T, getParent, Instance } from 'mobx-state-tree' -import type { TRootStore, TAccount, TRoute } from '@/spec' -import { markStates, buildLog } from '@/utils' +import type { TRootStore, TAccount, TRoute, TCommunity } from '@/spec' +import { markStates, buildLog, sortByIndex } from '@/utils' /* eslint-disable-next-line */ const log = buildLog('S:CommunityContent') @@ -21,6 +21,14 @@ const CommunityContent = T.model('CommunityContent', {}) const root = getParent(self) as TRootStore return root.accountInfo }, + get subscribedCommunitiesData(): TCommunity[] { + const root = getParent(self) as TRootStore + const { subscribedCommunities } = root.account + + return subscribedCommunities + ? sortByIndex(subscribedCommunities.entries) + : [] + }, })) .actions((self) => ({ setViewing(sobj): void { diff --git a/src/containers/content/CommunityContent/styles/index.ts b/src/containers/content/CommunityContent/styles/index.ts index 34e050b69..bc566d00a 100755 --- a/src/containers/content/CommunityContent/styles/index.ts +++ b/src/containers/content/CommunityContent/styles/index.ts @@ -1,12 +1,24 @@ import styled from 'styled-components' -import type { TTestable } from '@/spec' +import type { TTestable, TC11NLayout } from '@/spec' +import { C11N } from '@/constant' import { theme, css, WIDTH, pixelAdd } from '@/utils' +type TWrapper = TTestable & { layout: TC11NLayout } + export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ 'data-test-id': testid, -}))` +}))` ${css.flex('justify-center')}; + + flex-direction: ${({ layout }) => { + return layout === C11N.CLASSIC ? 'column' : 'row' + }}; + + align-items: ${({ layout }) => { + return layout === C11N.CLASSIC ? 'center' : 'flex-start' + }}; + min-height: 70vh; width: 100%; @@ -18,22 +30,33 @@ export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ padding-right: 0; `}; ` -export const InnerWrapper = styled.div<{ cardView: boolean }>` +export const InnerWrapper = styled.div<{ isClassicLayout: boolean }>` margin-top: 20px; width: 100%; - max-width: ${pixelAdd(WIDTH.COMMUNITY.CONTENT, 46)}; - margin-left: ${WIDTH.COMMUNITY.CONTENT_OFFSET}; - /* padding-left: 25px; */ - /* padding-right: 10px; */ + /* max-width: ${pixelAdd(WIDTH.COMMUNITY.CONTENT, 46)}; */ + /* margin-left: ${WIDTH.COMMUNITY.CONTENT_OFFSET}; */ - padding-top: ${({ cardView }) => (cardView ? '12px' : '0')}; - color: ${theme('font')}; - /* background: ${theme('content.bg')}; */ + max-width: ${({ isClassicLayout }) => + isClassicLayout + ? pixelAdd(WIDTH.COMMUNITY.CONTENT, 46) + : WIDTH.COMMUNITY.CONTENT}; - /* border: 1px solid; - border-color: ${theme('content.border')}; */ - /* border-radius: 6px; */ + margin-left: ${({ isClassicLayout }) => + /* TODO: 10px when HolyGrailLayout, make it center in "human feel" */ + isClassicLayout ? WIDTH.COMMUNITY.CONTENT_OFFSET : '10px'}; + + ${css.flex()}; + flex-direction: ${({ isClassicLayout }) => + isClassicLayout ? 'column' : 'row'}; + + padding-top: 0; + + /* 经典布局在统一宽度下再缩减 35px, 否则列表页会太宽 */ + padding-left: ${({ isClassicLayout }) => (isClassicLayout ? '35px' : 0)}; + padding-right: ${({ isClassicLayout }) => (isClassicLayout ? '35px' : 0)}; + + color: ${theme('font')}; ${css.media.mobile` margin: 0 3%; diff --git a/src/containers/content/CommunityContent/styles/subscribed_list/expand_button.ts b/src/containers/content/CommunityContent/styles/subscribed_list/expand_button.ts new file mode 100644 index 000000000..3a47dd912 --- /dev/null +++ b/src/containers/content/CommunityContent/styles/subscribed_list/expand_button.ts @@ -0,0 +1,30 @@ +import styled from 'styled-components' + +import Img from '@/Img' +import { css, theme } from '@/utils' + +export const Wrapper = styled.div` + ${css.flex('align-center')}; + cursor: pointer; +` +export const ArrowIcon = styled(Img)<{ reverse?: boolean }>` + ${css.size(14)}; + fill: ${theme('thread.articleDigest')}; + transform: ${({ reverse }) => (reverse ? 'rotate(180deg)' : '')}; + ${Wrapper}:hover & { + fill: ${theme('thread.articleTitle')}; + } + + transition: all 0.25s; +` +export const Text = styled.div` + color: ${theme('thread.articleDigest')}; + font-size: 14px; + margin-left: 8px; + + ${Wrapper}:hover & { + fill: ${theme('thread.articleTitle')}; + } + + transition: all 0.25s; +` diff --git a/src/containers/content/CommunityContent/styles/subscribed_list/index.ts b/src/containers/content/CommunityContent/styles/subscribed_list/index.ts new file mode 100644 index 000000000..37eb66c25 --- /dev/null +++ b/src/containers/content/CommunityContent/styles/subscribed_list/index.ts @@ -0,0 +1,101 @@ +import styled from 'styled-components' + +import Img from '@/Img' +import { css, theme } from '@/utils' + +export const Wrapper = styled.div` + width: 132px; + min-width: 132px; + margin-top: 10px; + margin-right: 20px; + height: 400px; + color: #5b7b81; + padding-top: 10px; + padding-left: 10px; +` +export const HeadTitle = styled.div` + ${css.flex('align-center')}; + font-size: 14px; + font-weight: bold; +` +export const HeadNum = styled.div` + color: ${theme('thread.articleDigest')}; + font-size: 12px; + opacity: 0.9; + margin-top: 1px; + font-weight: normal; +` +export const Divider = styled.div` + width: 80px; + height: 1px; + background: #004757; + margin-top: 8px; + margin-bottom: 10px; +` +export const Item = styled.div` + ${css.flex('align-center')}; + font-size: 14px; + margin-bottom: 15px; + + &:hover { + cursor: pointer; + } +` +export const Logo = styled(Img)` + fill: ${theme('thread.articleDigest')}; + ${css.size(18)}; + border-radius: 5px; + margin-right: 7px; + filter: saturate(0.5); +` +export const Title = styled.div` + ${css.cutRest('70px')}; + + ${Item}:hover & { + color: ${theme('thread.articleTitle')}; + } +` + +export const Option = styled.div`` +export const OptionIcon = styled(Img)` + ${css.size(15)}; + fill: ${theme('thread.articleDigest')}; + transform: rotate(90deg); + opacity: 0; + + &:hover { + fill: ${theme('thread.articleTitle')}; + cursor: pointer; + } + + ${Item}:hover & { + opacity: 1; + } +` + +export const Menu = styled.div` + padding: 8px; + padding-bottom: 2px; +` +export const MenuItem = styled.div` + ${css.flex('align-center')}; + margin-bottom: 8px; + cursor: pointer; +` +export const MenuIcon = styled(Img)` + ${css.size(14)}; + fill: ${theme('thread.articleDigest')}; + + ${MenuItem}:hover & { + fill: ${theme('thread.articleTitle')}; + } +` +export const MenuTitle = styled.div` + font-size: 13px; + fill: ${theme('thread.articleDigest')}; + margin-left: 5px; + + ${MenuItem}:hover & { + color: ${theme('thread.articleTitle')}; + } +` diff --git a/src/containers/content/CommunityContent/styles/subscribed_list/item_menu.ts b/src/containers/content/CommunityContent/styles/subscribed_list/item_menu.ts new file mode 100644 index 000000000..5a0759e57 --- /dev/null +++ b/src/containers/content/CommunityContent/styles/subscribed_list/item_menu.ts @@ -0,0 +1,31 @@ +import styled from 'styled-components' + +import Img from '@/Img' +import { css, theme } from '@/utils' + +export const Wrapper = styled.div` + padding: 8px; + padding-bottom: 2px; +` +export const Item = styled.div` + ${css.flex('align-center')}; + margin-bottom: 8px; + cursor: pointer; +` +export const Icon = styled(Img)` + ${css.size(14)}; + fill: ${theme('thread.articleDigest')}; + + ${Item}:hover & { + fill: ${theme('thread.articleTitle')}; + } +` +export const Title = styled.div` + font-size: 13px; + fill: ${theme('thread.articleDigest')}; + margin-left: 5px; + + ${Item}:hover & { + color: ${theme('thread.articleTitle')}; + } +` diff --git a/src/containers/digest/CommunityDigest/BriefView.js b/src/containers/digest/CommunityDigest/BriefView.js deleted file mode 100755 index 0e4ccac22..000000000 --- a/src/containers/digest/CommunityDigest/BriefView.js +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react' - -// import { ICON_CMD } from '@/config' -import TabBar from '@/components/TabBar' - -import { - Wrapper, - BannerContentWrapper, - TabBarWrapper, -} from './styles/brief_view' - -import { tabOnChange } from './logic' - -const BriefView = ({ community, activeThread, layout }) => ( - - - - - - - -) - -export default React.memo(BriefView) diff --git a/src/containers/digest/CommunityDigest/ClassicView/CommunityBrief.tsx b/src/containers/digest/CommunityDigest/ClassicView/CommunityBrief.tsx new file mode 100644 index 000000000..01417aab5 --- /dev/null +++ b/src/containers/digest/CommunityDigest/ClassicView/CommunityBrief.tsx @@ -0,0 +1,60 @@ +import { FC, memo } from 'react' +import { contains } from 'ramda' + +import type { TCommunity } from '@/spec' +import { ICON_CMD } from '@/config' +import { HCN, NON_FILL_COMMUNITY } from '@/constant' + +import VerifiedSign from '@/components/VerifiedSign' + +import ExpandTexts from '../ExpandTexts' +import SocialList from '../SocialList' + +import { + Wrapper, + Logo, + LogoWrapper, + CommunityInfo, + TitleWrapper, + Title, + TitleText, + LogoHolder, +} from '../styles/classic_view/community_brief' + +const CommunityLogoHolder = `${ICON_CMD}/community_logo_holder.svg` + +type TProps = { + community: TCommunity + descExpand: boolean +} + +const CommunityBrief: FC = ({ community, descExpand }) => { + return ( + + + {community.logo ? ( + + ) : ( + + )} + + + + + <TitleText>{community.title}</TitleText> + <VerifiedSign /> + + + {/* {community.desc} */} + + {community.raw !== HCN && } + + + ) +} + +export default memo(CommunityBrief) diff --git a/src/containers/digest/CommunityDigest/DigestView/ColumnView/index.js b/src/containers/digest/CommunityDigest/ClassicView/index.tsx similarity index 50% rename from src/containers/digest/CommunityDigest/DigestView/ColumnView/index.js rename to src/containers/digest/CommunityDigest/ClassicView/index.tsx index cdb26e902..2e251d81a 100644 --- a/src/containers/digest/CommunityDigest/DigestView/ColumnView/index.js +++ b/src/containers/digest/CommunityDigest/ClassicView/index.tsx @@ -1,18 +1,15 @@ -import React from 'react' +import { FC, memo } from 'react' import { contains } from 'ramda' import { Waypoint } from 'react-waypoint' -import { ICON_CMD } from '@/config' -import { HCN, NON_FILL_COMMUNITY } from '@/constant' +import type { TC11NLayout, TThread, TCommunity } from '@/spec' +import { HCN } from '@/constant' import { useDevice } from '@/hooks' -import VerifiedSign from '@/components/VerifiedSign' import TabBar from '@/components/TabBar' import CommunityStatesPad from '@/components/CommunityStatesPad' -import { CommunityHolder } from '@/components/LoadingEffects' -import ExpandTexts from '../../ExpandTexts' -import SocialList from '../../SocialList' +import CommunityBrief from './CommunityBrief' import { Wrapper, @@ -20,60 +17,27 @@ import { BannerContentWrapper, CommunityBaseInfo, TabBarWrapper, - CommunityWrapper, - CommunityLogo, - LogoWrapper, - CommunityInfo, - TitleWrapper, - Title, - TitleText, - LogoHolder, -} from '../../styles/digest_view/column_view' +} from '../styles/classic_view' import { tabOnChange, onShowEditorList, onShowSubscriberList, setViewport, -} from '../../logic' - -const CommunityLogoHolder = `${ICON_CMD}/community_logo_holder.svg` +} from '../logic' // 没有各种外链接,打赏信息等的官方社区 const NON_STANDARD_COMMUNITIES = [HCN, 'feedback'] -const CommunityBrief = ({ content, descExpand }) => { - return ( - - - {content.logo ? ( - } - /> - ) : ( - - )} - - - - - <TitleText>{content.title}</TitleText> - <VerifiedSign /> - - - {/* {content.desc} */} - - {content.raw !== HCN && } - - - ) +type TProps = { + community: TCommunity + descExpand: boolean + activeThread: TThread + layout: TC11NLayout + metric: string } -const ColumnView = ({ +const ClassicView: FC = ({ community, descExpand, activeThread, @@ -84,6 +48,7 @@ const ColumnView = ({ return ( - + { - return ( - - - {title} - <Num>{num}</Num> - - - - 查看 - - - - ) -} - -export default React.memo(SubTitle) diff --git a/src/containers/digest/CommunityDigest/DigestView/RowView/SubscribeInfo.js b/src/containers/digest/CommunityDigest/DigestView/RowView/SubscribeInfo.js deleted file mode 100644 index f5c6d8499..000000000 --- a/src/containers/digest/CommunityDigest/DigestView/RowView/SubscribeInfo.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react' - -import { ICON } from '@/config' -import { FollowButton } from '@/components/Buttons' - -import { - Wrapper, - Item, - StateItem, - Icon, - OnlineDot, - Desc, -} from '../../styles/digest_view/row_view/subscribe_info' - -const SubscribeInfo = () => { - return ( - - - - - 2237 人关注 - - - - - - - 22 在线 - - - - ) -} - -export default SubscribeInfo diff --git a/src/containers/digest/CommunityDigest/DigestView/RowView/index.js b/src/containers/digest/CommunityDigest/DigestView/RowView/index.js deleted file mode 100644 index cfd7a953e..000000000 --- a/src/containers/digest/CommunityDigest/DigestView/RowView/index.js +++ /dev/null @@ -1,134 +0,0 @@ -import React from 'react' -import { contains } from 'ramda' - -import { HCN, THREAD, NON_FILL_COMMUNITY, VIEW } from '@/constant' -import { ICON_CMD } from '@/config' - -import CustomScroller from '@/components/CustomScroller' -import TabBar from '@/components/TabBar' -import TagsBar from '@/containers/unit/TagsBar' - -// import { SpaceGrow } from '@/components/Common' -import Sticky from '@/components/Sticky' -import VerifiedSign from '@/components/VerifiedSign' -import { CommunityHolder } from '@/components/LoadingEffects' -// import CommunityStatesPad from '@/components/CommunityStatesPad' - -import ExpandTexts from '../../ExpandTexts' -import SocialList from '../../SocialList' - -import SubTitle from './SubTitle' -import SubscribeInfo from './SubscribeInfo' -import TeamList from './TeamList' - -import { - Wrapper, - ContentWrapper, - InnerWrapper, - BannerContentWrapper, - CommunityWrapper, - CommunityLogo, - CommunityInfo, - TitleWrapper, - Title, - TitleText, - LogoHolder, - Divider, - TabBarWrapper, -} from '../../styles/digest_view/row_view' - -import { tabOnChange } from '../../logic' - -// import { -// onShowEditorList, -// onShowSubscriberList, -// } from '../../logic' - -const CommunityLogoHolder = `${ICON_CMD}/community_logo_holder.svg` - -// 没有各种外链接,打赏信息等的官方社区 -const NON_STANDARD_COMMUNITIES = [HCN, 'feedback'] - -const CommunityBrief = ({ content, descExpand }) => { - return ( - - {content.logo ? ( - } - /> - ) : ( - - )} - - - - <TitleText>{content.title}</TitleText> - <VerifiedSign /> - - - - - - ) -} - -const RowView = ({ community, descExpand, isHeaderFixed, activeThread }) => { - const offsetTop = isHeaderFixed ? 55 : 30 - - return ( - - - - - - - - - - - - - - - - - - {/* */} - - - - - - - - - - - ) -} - -export default React.memo(RowView) diff --git a/src/containers/digest/CommunityDigest/DigestView/index.js b/src/containers/digest/CommunityDigest/DigestView/index.js deleted file mode 100644 index 1017401cf..000000000 --- a/src/containers/digest/CommunityDigest/DigestView/index.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react' - -import { C11N } from '@/constant' -import { useDevice } from '@/hooks' - -import ColumnView from './ColumnView' -import RowView from './RowView' - -const DigestView = ({ layout, ...rest }) => { - const { isMobile } = useDevice() - - if (isMobile) { - return - } - - return ( - - {layout === C11N.DIGEST ? ( - - ) : ( - - )} - - ) -} - -export default DigestView diff --git a/src/containers/digest/CommunityDigest/ExpandTexts.js b/src/containers/digest/CommunityDigest/ExpandTexts.tsx similarity index 88% rename from src/containers/digest/CommunityDigest/ExpandTexts.js rename to src/containers/digest/CommunityDigest/ExpandTexts.tsx index 213ccaab0..a37c206e9 100644 --- a/src/containers/digest/CommunityDigest/ExpandTexts.js +++ b/src/containers/digest/CommunityDigest/ExpandTexts.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { FC, memo } from 'react' import { ICON_CMD } from '@/config' import { useDevice } from '@/hooks' @@ -19,12 +19,16 @@ import { toggleDescExpand } from './logic' const text = '全球疫情催生了很多断章取义的新闻,我发现各路媒体现在特别会抓网民的爽点深谙撩拨之道,知道哪里轻轻一碰,就会引发高潮。美国和欧洲在疫情早期判断错误,死硬到底拒不管制,现在被现实打脸纷纷封城,这种剧情反转的打脸情节特别爽,以至于这条“巴西黑帮封城”的新闻.' -const ExpandTexts = ({ descExpand }) => { +type TProps = { + descExpand: boolean +} + +const ExpandTexts: FC = ({ descExpand }) => { const { isMobile } = useDevice() const cutLength = !isMobile ? 26 : 10 return ( - + {descExpand ? ( {text} @@ -47,4 +51,4 @@ const ExpandTexts = ({ descExpand }) => { ) } -export default React.memo(ExpandTexts) +export default memo(ExpandTexts) diff --git a/src/containers/digest/CommunityDigest/SocialList.js b/src/containers/digest/CommunityDigest/SocialList.tsx similarity index 64% rename from src/containers/digest/CommunityDigest/SocialList.js rename to src/containers/digest/CommunityDigest/SocialList.tsx index cf6051309..ffd8f4d98 100644 --- a/src/containers/digest/CommunityDigest/SocialList.js +++ b/src/containers/digest/CommunityDigest/SocialList.tsx @@ -1,16 +1,12 @@ -import React from 'react' -import T from 'prop-types' +import { FC, memo } from 'react' +import type { TSIZE_SM } from '@/spec' import { ICON_CMD } from '@/config' import { SIZE } from '@/constant' import { Wrapper, SocialWrapper, Icon } from './styles/social_list' const defaultItems = [ - { - iconSrc: `${ICON_CMD}/navi/readme.svg`, - title: '项目介绍', - }, // { // iconSrc: `${ICON_CMD}/navi/location.svg`, // title: '成都', @@ -33,11 +29,22 @@ const defaultItems = [ }, ] -const SocialList = ({ size, items }) => { +type TProps = { + size?: TSIZE_SM + items?: { + iconSrc: string + title: string + }[] +} + +const SocialList: FC = ({ + size = SIZE.SMALL, + items = defaultItems, +}) => { return ( {items.map((item) => ( - + {/* {item.title} @@ -48,14 +55,4 @@ const SocialList = ({ size, items }) => { ) } -SocialList.propTypes = { - size: T.oneOf([SIZE.SMALL, SIZE.MEDIUM]), - items: T.arrayOf(T.object), -} - -SocialList.defaultProps = { - size: SIZE.SMALL, - items: defaultItems, -} - -export default React.memo(SocialList) +export default memo(SocialList) diff --git a/src/containers/digest/CommunityDigest/index.js b/src/containers/digest/CommunityDigest/index.js deleted file mode 100755 index 1d3b498cd..000000000 --- a/src/containers/digest/CommunityDigest/index.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * CommunityDigest - * - */ -import React from 'react' - -import { C11N } from '@/constant' -import { pluggedIn, buildLog } from '@/utils' - -import DigestView from './DigestView/index' -import BriefView from './BriefView' - -import { Wrapper } from './styles' -import { useInit } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:CommunityDigest') - -const CommunityDigestContainer = ({ communityDigest: store, metric }) => { - useInit(store) - - const { - accountInfo: { - customization: { bannerLayout }, - }, - viewing: { community, activeThread }, - descExpand, - isHeaderFixed, - } = store - - return ( - <Wrapper testid="community-digest"> - {bannerLayout === C11N.BRIEF ? ( - <BriefView - metric={metric} - community={community} - activeThread={activeThread} - layout={bannerLayout} - /> - ) : ( - <DigestView - metric={metric} - community={community} - activeThread={activeThread} - layout={bannerLayout} - descExpand={descExpand} - isHeaderFixed={isHeaderFixed} - /> - )} - </Wrapper> - ) -} - -export default pluggedIn(CommunityDigestContainer) diff --git a/src/containers/digest/CommunityDigest/index.tsx b/src/containers/digest/CommunityDigest/index.tsx new file mode 100755 index 000000000..bb77ab3c0 --- /dev/null +++ b/src/containers/digest/CommunityDigest/index.tsx @@ -0,0 +1,50 @@ +/* + * + * CommunityDigest + * + */ +import { FC } from 'react' + +import { METRIC } from '@/constant' +import { pluggedIn, buildLog } from '@/utils' + +import ClassicView from './ClassicView' + +import type { TStore } from './store' +import { useInit } from './logic' + +/* eslint-disable-next-line */ +const log = buildLog('C:CommunityDigest') + +type TProps = { + communityDigest?: TStore + metric?: string +} + +const CommunityDigestContainer: FC<TProps> = ({ + communityDigest: store, + metric = METRIC.COMMUNITY, +}) => { + useInit(store) + + const { + accountInfo: { + customization: { bannerLayout }, + }, + curThread, + curCommunity, + descExpand, + } = store + + return ( + <ClassicView + metric={metric} + community={curCommunity} + activeThread={curThread} + layout={bannerLayout} + descExpand={descExpand} + /> + ) +} + +export default pluggedIn(CommunityDigestContainer) as FC<TProps> diff --git a/src/containers/digest/CommunityDigest/logic.js b/src/containers/digest/CommunityDigest/logic.ts similarity index 83% rename from src/containers/digest/CommunityDigest/logic.js rename to src/containers/digest/CommunityDigest/logic.ts index 996386b7b..877ceb9df 100755 --- a/src/containers/digest/CommunityDigest/logic.js +++ b/src/containers/digest/CommunityDigest/logic.ts @@ -1,6 +1,9 @@ import { useEffect } from 'react' import { TYPE, EVENT, ERR } from '@/constant' + +import type { TThread } from '@/spec' + import { asyncSuit, buildLog, @@ -10,18 +13,20 @@ import { errRescue, } from '@/utils' +import type { TStore } from './store' import S from './schema' /* eslint-disable-next-line */ const log = buildLog('L:CommunityDigest') const { SR71, $solver, asyncRes, asyncErr } = asyncSuit +// @ts-ignore const sr71$ = new SR71({ receive: [EVENT.COMMUNITY_CHANGE] }) let sub$ = null -let store = null +let store: TStore | undefined -const loadCommunity = () => { +const loadCommunity = (): void => { const userHasLogin = store.isLogin const { raw } = store.curCommunity @@ -30,7 +35,7 @@ const loadCommunity = () => { sr71$.query(S.community, { raw, userHasLogin }) } -export const tabOnChange = (activeThread) => { +export const tabOnChange = (activeThread: TThread): void => { const subPath = thread2Subpath(activeThread) // log('EVENT.activeThread -----> ', activeThread) // log('EVENT.subPath -----> ', subPath) @@ -41,27 +46,27 @@ export const tabOnChange = (activeThread) => { send(EVENT.THREAD_CHANGE, { data: { activeThread } }) } -export const onShowEditorList = () => { +export const onShowEditorList = (): void => { const type = TYPE.USER_LISTER_COMMUNITY_EDITORS const data = { - id: store.viewing.community.id, - brief: store.viewing.community.title, + id: store.curCommunity.id, + brief: store.curCommunity.title, } send(EVENT.USER_LISTER_OPEN, { type, data }) } -export const onShowSubscriberList = () => { +export const onShowSubscriberList = (): void => { const type = TYPE.USER_LISTER_COMMUNITY_SUBSCRIBERS const data = { - id: store.viewing.community.id, - brief: store.viewing.community.title, + id: store.curCommunity.id, + brief: store.curCommunity.title, } send(EVENT.USER_LISTER_OPEN, { type, data }) } -export const toggleDescExpand = () => { +export const toggleDescExpand = (): void => { const { descExpand } = store store.mark({ descExpand: !descExpand }) @@ -73,7 +78,7 @@ const markLoading = (maybe = true) => store.mark({ loading: maybe }) * set digest visible in current viewport * @param {Boolean} inView */ -export const setViewport = (inViewport) => { +export const setViewport = (inViewport: boolean): void => { store.mark({ inViewport }) } @@ -137,7 +142,7 @@ const ErrSolver = [ // ############################### // init & uninit // ############################### -export const useInit = (_store) => { +export const useInit = (_store: TStore): void => { useEffect(() => { store = _store // log('effect init') diff --git a/src/containers/digest/CommunityDigest/store.js b/src/containers/digest/CommunityDigest/store.js deleted file mode 100755 index d5ff8ec65..000000000 --- a/src/containers/digest/CommunityDigest/store.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * CommunityDigest store - * - */ - -import { types as T, getParent } from 'mobx-state-tree' - -import { markStates, buildLog, stripMobx } from '@/utils' - -/* eslint-disable-next-line */ -const log = buildLog('S:CommunityDigest') - -const CommunityDigest = T.model('CommunityDigest', { - loading: T.optional(T.boolean, false), - descExpand: T.optional(T.boolean, false), - - inViewport: T.optional(T.boolean, true), -}) - .views((self) => ({ - get root() { - return getParent(self) - }, - get isLogin() { - return self.root.account.isLogin - }, - get isHeaderFixed() { - return self.root.header.fixed - }, - get curRoute() { - return self.root.curRoute - }, - get viewing() { - return stripMobx(self.root.viewing) - }, - get accountInfo() { - return self.root.accountInfo - }, - get curCommunity() { - return stripMobx(self.root.viewing.community) - }, - })) - .actions((self) => ({ - authWarning(options) { - self.root.authWarning(options) - }, - markRoute(query) { - self.root.markRoute(query) - }, - setViewing(sobj) { - self.root.setViewing(sobj) - }, - addSubscribedCommunity(community) { - self.root.account.addSubscribedCommunity(community) - }, - removeSubscribedCommunity(community) { - self.root.account.removeSubscribedCommunity(community) - }, - mark(sobj) { - markStates(sobj, self) - }, - })) - -export default CommunityDigest diff --git a/src/containers/digest/CommunityDigest/store.ts b/src/containers/digest/CommunityDigest/store.ts new file mode 100755 index 000000000..37d233bb2 --- /dev/null +++ b/src/containers/digest/CommunityDigest/store.ts @@ -0,0 +1,81 @@ +/* + * CommunityDigest store + * + */ + +import { types as T, getParent, Instance } from 'mobx-state-tree' + +import type { + TRootStore, + TViewing, + TRoute, + TCommunity, + TAccount, + TThread, +} from '@/spec' +import { markStates, buildLog, stripMobx } from '@/utils' + +/* eslint-disable-next-line */ +const log = buildLog('S:CommunityDigest') + +const CommunityDigest = T.model('CommunityDigest', { + loading: T.optional(T.boolean, false), + descExpand: T.optional(T.boolean, false), + + inViewport: T.optional(T.boolean, true), +}) + .views((self) => ({ + get isLogin(): boolean { + const root = getParent(self) as TRootStore + return root.account.isLogin + }, + get curRoute(): TRoute { + const root = getParent(self) as TRootStore + return root.curRoute + }, + get viewing(): TViewing { + const root = getParent(self) as TRootStore + return stripMobx(root.viewing) + }, + get accountInfo(): TAccount { + const root = getParent(self) as TRootStore + return root.accountInfo + }, + get curThread(): TThread { + const root = getParent(self) as TRootStore + return root.viewing.activeThread + }, + get curCommunity(): TCommunity { + const root = getParent(self) as TRootStore + + return stripMobx(root.viewing.community) + }, + })) + .actions((self) => ({ + authWarning(options): void { + const root = getParent(self) as TRootStore + root.authWarning(options) + }, + markRoute(query): void { + const root = getParent(self) as TRootStore + root.markRoute(query) + }, + setViewing(sobj): void { + const root = getParent(self) as TRootStore + root.setViewing(sobj) + }, + addSubscribedCommunity(community: TCommunity): void { + const root = getParent(self) as TRootStore + root.account.addSubscribedCommunity(community) + }, + removeSubscribedCommunity(community: TCommunity): void { + const root = getParent(self) as TRootStore + root.account.removeSubscribedCommunity(community) + }, + mark(sobj: Record<string, unknown>): void { + markStates(sobj, self) + }, + })) + +export type TStore = Instance<typeof CommunityDigest> +export default CommunityDigest diff --git a/src/containers/digest/CommunityDigest/styles/brief_view.ts b/src/containers/digest/CommunityDigest/styles/brief_view.ts deleted file mode 100755 index fc028fe3a..000000000 --- a/src/containers/digest/CommunityDigest/styles/brief_view.ts +++ /dev/null @@ -1,30 +0,0 @@ -import styled from 'styled-components' - -import { css, WIDTH } from '@/utils' -import { BaseBanner } from './index' - -export const Wrapper = styled(BaseBanner)` - min-height: 45px; -` -export const BaseBannerContent = styled.div` - ${css.flex()}; -` -export const BannerContainer = styled(BaseBanner)`` - -export const TabBarWrapper = styled.div` - ${css.flex()}; - max-width: ${WIDTH.COMMUNITY.PAGE}; - width: 100%; - /* 150 is the breif card width */ - padding-left: calc(155px + 6vw); - - ${css.media.mobile` - width: 55vw; - overflow: scroll; - margin-left: 45vw; - `}; -` -export const BannerContentWrapper = styled(BaseBannerContent)` - width: 100%; - ${css.flex('justify-center')}; -` diff --git a/src/containers/digest/CommunityDigest/styles/classic_view/community_brief.ts b/src/containers/digest/CommunityDigest/styles/classic_view/community_brief.ts new file mode 100644 index 000000000..d3c51da49 --- /dev/null +++ b/src/containers/digest/CommunityDigest/styles/classic_view/community_brief.ts @@ -0,0 +1,69 @@ +import styled from 'styled-components' + +import { HCN } from '@/constant' +import { theme, css } from '@/utils' +import Img from '@/Img' + +import CommunityFaceLogo from '@/components/CommunityFaceLogo' + +export const Wrapper = styled.div<{ descExpand: boolean }>` + ${css.flexGrow('align-center')}; + align-items: ${({ descExpand }) => (descExpand ? 'flex-start' : 'center')}; + transition: all 0.5s; +` +export const LogoWrapper = styled.div<{ raw: string }>` + position: relative; + width: 55px; + /* TODO: use new logo */ + margin-top: ${({ raw }) => (raw === HCN ? '-10px' : 0)}; + + @media (max-height: 800px) { + margin-top: ${({ raw }) => (raw === HCN ? '-8px' : 0)}; + } + + ${css.media.mobile` + width: 45px; + margin-top: -2px; + `}; +` +export const Logo = styled(CommunityFaceLogo)` + ${css.size(45)}; + border-radius: 5px; + + ${css.media.mobile` + width: 36px; + height: 36px; + `}; +` +export const CommunityInfo = styled.div` + ${css.flexColumn('justify-center')}; + + margin-top: -6px; + margin-left: 12px; + + ${css.media.mobile` + margin-left: ${({ descExpand }) => (descExpand ? '12px' : '3px')}; + `}; +` +export const TitleWrapper = styled.div` + ${css.flex('align-center')}; +` +export const Title = styled.div<{ descExpand: boolean }>` + ${css.flex('align-baseline')}; + font-size: ${({ descExpand }) => (descExpand ? '21px' : '18px')}; + color: ${theme('banner.title')}; +` +export const TitleText = styled.span` + margin-right: 10px; +` +export const LogoHolder = styled(Img)` + fill: ${theme('banner.desc')}; + width: 50px; + height: 50px; + @media (max-height: 800px) { + width: 40px; + height: 40px; + } + opacity: 0.6; + margin-top: 3px; +` diff --git a/src/containers/digest/CommunityDigest/styles/classic_view/index.ts b/src/containers/digest/CommunityDigest/styles/classic_view/index.ts new file mode 100644 index 000000000..7da2d3b28 --- /dev/null +++ b/src/containers/digest/CommunityDigest/styles/classic_view/index.ts @@ -0,0 +1,75 @@ +import styled from 'styled-components' + +import { css, WIDTH, pixelAdd } from '@/utils' + +import { BaseBanner } from '../index' + +const getMinHeight = (noSocial, isMobile) => { + if (isMobile) { + return noSocial ? '112px' : '140px' + } + + return noSocial ? '128px' : '150px' +} + +type TWrapper = { + descExpand: boolean + noSocial: boolean + isMobile: boolean + metric?: string +} +export const Wrapper = styled(BaseBanner)<TWrapper>` + width: 100%; + min-height: ${({ descExpand, noSocial, isMobile }) => + descExpand ? '300px' : getMinHeight(noSocial, isMobile)}; +` +export const InnerWrapper = styled.div<TWrapper>` + ${css.flex('justify-center')}; + padding-top: 20px; + min-height: ${({ descExpand, noSocial, isMobile }) => + descExpand ? '300px' : getMinHeight(noSocial, isMobile)}; + width: 100%; + // if use margin-left will cause horizontal scrollbar + // 70 是经典布局为缩小帖子列表"视觉宽度"手动缩小的值 + padding-left: ${pixelAdd(WIDTH.COMMUNITY.CONTENT_OFFSET, 70)}; + ${({ metric }) => css.fitPageWidth(metric)}; + transition: min-height 0.25s; +` +export const BaseBannerContent = styled.div` + ${css.flexColumn('align-center')}; + width: 100%; + max-width: ${WIDTH.COMMUNITY.CONTENT}; + + ${css.media.mobile` + padding-left: 6%; + padding-right: 5.5%; + `}; +` +type TBannerContent = { descExpand: boolean } +export const BannerContentWrapper = styled(BaseBannerContent)<TBannerContent>` + ${css.flexColumn('justify-between')}; + align-items: ${({ descExpand }) => (descExpand ? 'flex-start' : 'center')}; +` +export const BannerContainer = styled(BaseBanner)` + /* min-height: 125px; */ +` +export const TabBarWrapper = styled.div` + ${css.flex()}; + width: 100%; + margin-left: -16px; + + ${css.media.tablet` + padding-left: calc(2%); + `}; + + ${css.media.mobile` + padding-left: 0; + margin-left: -10px; + `}; +` +export const CommunityBaseInfo = styled.div` + ${css.flex('justify-between')}; + width: 100%; + // 60 是经典布局为缩小帖子列表"视觉宽度"手动缩小的值 + padding-right: 60px; +` diff --git a/src/containers/digest/CommunityDigest/styles/digest_view/column_view/index.ts b/src/containers/digest/CommunityDigest/styles/digest_view/column_view/index.ts deleted file mode 100644 index 9ce96217b..000000000 --- a/src/containers/digest/CommunityDigest/styles/digest_view/column_view/index.ts +++ /dev/null @@ -1,153 +0,0 @@ -import styled from 'styled-components' - -import { HCN } from '@/constant' -import { theme, css, WIDTH } from '@/utils' -import Img from '@/Img' - -import CommunityFaceLogo from '@/components/CommunityFaceLogo' - -import { BaseBanner } from '../../index' - -const getMinHeight = (noSocial, isMobile) => { - if (isMobile) { - return noSocial ? '112px' : '140px' - } - - return noSocial ? '128px' : '150px' -} - -type TWrapper = { - descExpand: boolean - noSocial: boolean - isMobile: boolean - metric?: string -} -export const Wrapper = styled(BaseBanner)<TWrapper>` - min-height: ${({ descExpand, noSocial, isMobile }) => - descExpand ? '300px' : getMinHeight(noSocial, isMobile)}; -` -export const InnerWrapper = styled.div<TWrapper>` - ${css.flex('justify-center')}; - padding-top: 20px; - min-height: ${({ descExpand, noSocial, isMobile }) => - descExpand ? '300px' : getMinHeight(noSocial, isMobile)}; - width: 100%; - // if use margin-left will cause horizontal scrollbar - padding-left: ${WIDTH.COMMUNITY.CONTENT_OFFSET}; - ${({ metric }) => css.fitPageWidth(metric)}; - transition: min-height 0.25s; -` -export const BaseBannerContent = styled.div` - ${css.flexColumn('align-center')}; - width: 100%; - max-width: ${WIDTH.COMMUNITY.CONTENT}; - - ${css.media.mobile` - padding-left: 6%; - padding-right: 5.5%; - `}; -` -type TBannerContent = { descExpand: boolean } -export const BannerContentWrapper = styled(BaseBannerContent)<TBannerContent>` - ${css.flexColumn('justify-between')}; - align-items: ${({ descExpand }) => (descExpand ? 'flex-start' : 'center')}; -` -export const BannerContainer = styled(BaseBanner)` - /* min-height: 125px; */ -` -export const TabBarWrapper = styled.div` - ${css.flex()}; - width: 100%; - margin-left: -16px; - - ${css.media.tablet` - padding-left: calc(2%); - `}; - - ${css.media.mobile` - padding-left: 0; - margin-left: -10px; - `}; -` -export const CommunityBaseInfo = styled.div` - ${css.flex('justify-between')}; - width: 100%; -` -export const CommunityWrapper = styled.div<{ descExpand: string }>` - ${css.flexGrow('align-center')}; - align-items: ${({ descExpand }) => (descExpand ? 'flex-start' : 'center')}; - transition: all 0.5s; -` -export const LogoWrapper = styled.div<{ raw: string }>` - position: relative; - width: 55px; - /* TODO: use new logo */ - margin-top: ${({ raw }) => (raw === HCN ? '-10px' : 0)}; - - @media (max-height: 800px) { - margin-top: ${({ raw }) => (raw === HCN ? '-8px' : 0)}; - } - - ${css.media.mobile` - width: 45px; - margin-top: -2px; - `}; -` -export const CommunityLogo = styled(CommunityFaceLogo)<{ small: boolean }>` - width: ${({ small }) => (small ? '35px' : '45px')}; - height: ${({ small }) => (small ? '35px' : '45px')}; - border-radius: 5px; - - ${css.media.mobile` - width: 36px; - height: 36px; - `}; -` -export const CommunityInfo = styled.div` - ${css.flexColumn('justify-center')}; - - margin-top: -6px; - margin-left: 12px; - - ${css.media.mobile` - margin-left: ${({ descExpand }) => (descExpand ? '12px' : '3px')}; - `}; -` -export const TitleWrapper = styled.div` - ${css.flex('align-center')}; -` -export const Title = styled.div<{ descExpand: boolean }>` - ${css.flex('align-baseline')}; - font-size: ${({ descExpand }) => (descExpand ? '21px' : '18px')}; - color: ${theme('banner.title')}; -` -export const TitleText = styled.span` - margin-right: 10px; -` -export const GroupsIcon = styled(Img)` - fill: ${theme('banner.desc')}; - margin-left: 8px; - ${css.size(18)}; - margin-top: 5px; - opacity: 0; - &:hover { - cursor: pointer; - fill: ${theme('banner.title')}; - } - ${BannerContainer}:hover & { - fill: ${theme('banner.title')}; - opacity: 1; - } - transition: opacity 0.2s; -` -export const LogoHolder = styled(Img)` - fill: ${theme('banner.desc')}; - width: 50px; - height: 50px; - @media (max-height: 800px) { - width: 40px; - height: 40px; - } - opacity: 0.6; - margin-top: 3px; -` diff --git a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/index.ts b/src/containers/digest/CommunityDigest/styles/digest_view/row_view/index.ts deleted file mode 100644 index a763fb4cf..000000000 --- a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/index.ts +++ /dev/null @@ -1,111 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' - -import Img from '@/Img' -import CommunityFaceLogo from '@/components/CommunityFaceLogo' - -import { BaseBanner } from '../../index' - -export const Wrapper = styled(BaseBanner)<{ isHeaderFixed: boolean }>` - ${css.flexColumn('justify-start')}; - position: relative; - width: 280px; - height: ${({ isHeaderFixed }) => - isHeaderFixed ? 'calc(100vh - 70px)' : 'calc(100vh - 80px)'}; - margin-top: 20px; - margin-left: 30px; - border-radius: 5px; - transition: height 0.25s linear; -` -export const ContentWrapper = styled.div` - padding: 10px 20px; - padding-bottom: 20px; -` -export const InnerWrapper = styled.div` - ${css.flexColumn()}; - width: 100%; - height: 100%; -` -export const BaseBannerContent = styled.div` - ${css.flexColumn('align-start')}; - width: 100%; - height: 100%; - - ${css.media.mobile` - display: none; - `}; -` -/* align-items: ${({ descExpand }) => - descExpand ? 'flex-start' : 'center'}; */ -export const BannerContentWrapper = styled(BaseBannerContent)`` -export const BannerContainer = styled(BaseBanner)` - min-height: 125px; -` -export const Divider = styled.div` - width: 100%; - height: 1px; - background: #014758; - margin-top: 18px; - margin-bottom: 18px; -` -export const CommunityWrapper = styled.div` - ${css.flex('align-center', 'justify-center')}; - width: 100%; - transition: all 0.5s; - margin-top: 10px; - margin-bottom: 30px; -` -export const CommunityLogo = styled(CommunityFaceLogo)` - width: 50px; - height: 50px; - margin-right: 15px; - margin-left: -8px; - border-radius: 5px; -` -export const CommunityInfo = styled.div` - ${css.flexColumn('justify-center')}; -` -export const TitleWrapper = styled.div` - ${css.flex('align-center')}; - margin-bottom: 8px; -` -export const Title = styled.div<{ descExpand: boolean }>` - ${css.flex('align-baseline')}; - font-size: ${({ descExpand }) => (descExpand ? '21px' : '18px')}; - color: ${theme('banner.title')}; -` -export const TitleText = styled.span` - margin-right: 10px; -` -export const GroupsIcon = styled(Img)` - fill: ${theme('banner.desc')}; - margin-left: 8px; - ${css.size(18)}; - margin-top: 5px; - opacity: 0; - &:hover { - cursor: pointer; - fill: ${theme('banner.title')}; - } - ${BannerContainer}:hover & { - fill: ${theme('banner.title')}; - opacity: 1; - } - transition: opacity 0.2s; -` -export const LogoHolder = styled(Img)` - fill: ${theme('banner.desc')}; - width: 50px; - height: 50px; - @media (max-height: 800px) { - width: 40px; - height: 40px; - } - opacity: 0.6; - margin-top: 3px; -` -export const TabBarWrapper = styled.div` - width: 100%; - margin-bottom: 10px; -` diff --git a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/sub_title.ts b/src/containers/digest/CommunityDigest/styles/digest_view/row_view/sub_title.ts deleted file mode 100644 index 2dfa74f7a..000000000 --- a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/sub_title.ts +++ /dev/null @@ -1,29 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flex('align-center', 'justify-between')}; - width: 100%; - margin-bottom: 10px; -` -export const Title = styled.div` - ${css.flex('align-center')}; - color: ${theme('banner.desc')}; - font-size: 14px; - font-weight: bold; -` -export const Num = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 12px; - background: #054a5e; - padding: 0 5px; - border-radius: 6px; - line-height: 13px; - margin-left: 5px; -` -export const More = styled.div` - color: ${theme('banner.desc')}; - font-size: 12px; - width: 45px; -` diff --git a/src/containers/digest/CommunityDigest/styles/expand_texts.ts b/src/containers/digest/CommunityDigest/styles/expand_texts.ts index bcd235f7d..e1e4d2ccf 100644 --- a/src/containers/digest/CommunityDigest/styles/expand_texts.ts +++ b/src/containers/digest/CommunityDigest/styles/expand_texts.ts @@ -7,7 +7,7 @@ import { theme, css } from '@/utils' /* align-items: ${({ descExpand }) => descExpand ? 'flex-start' : 'center'}; */ export const Wrapper = styled.div`` -export const Normal = styled.div<{ margin: string }>` +export const Normal = styled.div<{ margin?: boolean }>` color: ${theme('banner.desc')}; font-size: 14px; max-width: 490px; diff --git a/src/containers/digest/CommunityDigest/styles/index.ts b/src/containers/digest/CommunityDigest/styles/index.ts index a5a141dcd..18cb3c9ab 100755 --- a/src/containers/digest/CommunityDigest/styles/index.ts +++ b/src/containers/digest/CommunityDigest/styles/index.ts @@ -3,15 +3,12 @@ import styled from 'styled-components' import type { TTestable } from '@/spec' import { theme, css } from '@/utils' -export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ +export const BaseBanner = styled.nav.attrs(({ testid }: TTestable) => ({ 'data-test-id': testid, }))<TTestable>` - width: 100%; -` -export const BaseBanner = styled.nav` ${css.flexColumn('justify-center', 'align-center')}; position: relative; - min-height: 140px; + min-height: 128px; background: ${theme('banner.bg')}; border-bottom: 1px solid; border-bottom-color: ${theme('banner.spliter')}; diff --git a/src/containers/digest/CommunityDigest/styles/social_list.ts b/src/containers/digest/CommunityDigest/styles/social_list.ts index 6a16b993a..985b52a76 100644 --- a/src/containers/digest/CommunityDigest/styles/social_list.ts +++ b/src/containers/digest/CommunityDigest/styles/social_list.ts @@ -1,5 +1,6 @@ import styled from 'styled-components' +import type { TSIZE_SM } from '@/spec' import { theme, css } from '@/utils' import Img from '@/Img' @@ -25,13 +26,13 @@ export const SocialWrapper = styled.div` cursor: pointer; } ` -export const Icon = styled(Img)<{ size: string }>` +export const Icon = styled(Img)<{ size: TSIZE_SM }>` fill: ${theme('banner.desc')}; border-radius: 50%; - width: ${({ size }) => (size === 'small' ? '14px;' : '17px')}; - height: ${({ size }) => (size === 'small' ? '14px;' : '17px')}; + width: ${({ size }) => (size === 'small' ? '13px;' : '17px')}; + height: ${({ size }) => (size === 'small' ? '13px;' : '17px')}; padding: 0; - margin-right: ${({ size }) => (size === 'small' ? '4px;' : '10px')}; + margin-right: ${({ size }) => (size === 'small' ? '2px' : '10px')}; display: block; ${SocialWrapper}:hover & { diff --git a/src/containers/layout/GlobalLayout/SEO.js b/src/containers/layout/GlobalLayout/SEO.tsx similarity index 87% rename from src/containers/layout/GlobalLayout/SEO.js rename to src/containers/layout/GlobalLayout/SEO.tsx index cede363a7..731eaddfa 100755 --- a/src/containers/layout/GlobalLayout/SEO.js +++ b/src/containers/layout/GlobalLayout/SEO.tsx @@ -4,13 +4,17 @@ * */ -import React from 'react' -import T from 'prop-types' +import { FC } from 'react' import { NextSeo, BlogJsonLd, SocialProfileJsonLd } from 'next-seo' import { METRIC } from '@/constant' -const SEO = (metric, config) => { +type TProps = { + metric: string + config: any +} + +const SEO: FC<TProps> = ({ metric, config }) => { switch (metric) { case METRIC.ARTICLE: { return ( @@ -59,9 +63,4 @@ const SEO = (metric, config) => { } } -SEO.propTypes = { - metric: T.string.isRequired, - config: T.object.isRequired, // TODO: -} - export default SEO diff --git a/src/containers/layout/GlobalLayout/index.tsx b/src/containers/layout/GlobalLayout/index.tsx index bd9bb4df2..c00117584 100755 --- a/src/containers/layout/GlobalLayout/index.tsx +++ b/src/containers/layout/GlobalLayout/index.tsx @@ -7,7 +7,7 @@ import React, { FC, ReactNode, useEffect } from 'react' import type { Nullable, TSEO } from '@/spec' -import { ANCHOR, SIZE } from '@/constant' +import { ANCHOR, SIZE, C11N } from '@/constant' import AnalysisService from '@/services/Analysis' import { useNetwork, useShortcut, usePlatform, useDevice } from '@/hooks' import { pluggedIn } from '@/utils' @@ -92,7 +92,7 @@ const GlobalLayoutContainer: FC<TProps> = ({ sidebarPin={sidebarPin} // noSidebar={noSidebar} > - {!noSidebar && <Sidebar />} + {!noSidebar && bannerLayout !== C11N.HOLY_GRAIL && <Sidebar />} <AbuseReport /> <Drawer /> <Doraemon /> diff --git a/src/containers/layout/GlobalLayout/styles/index.ts b/src/containers/layout/GlobalLayout/styles/index.ts index 24975957c..4cca1beae 100755 --- a/src/containers/layout/GlobalLayout/styles/index.ts +++ b/src/containers/layout/GlobalLayout/styles/index.ts @@ -48,7 +48,10 @@ export const BodyWrapper = styled.div<TBody>` ${css.flex('align-both')}; flex-direction: ${({ layout, isMobile }) => { if (isMobile) return 'column' - return layout === C11N.DIGEST ? 'column' : 'row' + return layout === C11N.CLASSIC ? 'column' : 'row-reverse' + }}; + align-items: ${({ layout }) => { + return layout === C11N.CLASSIC ? 'center' : 'flex-start' }}; width: 100%; ` diff --git a/src/containers/thread/BlogsThread/styles/index.ts b/src/containers/thread/BlogsThread/styles/index.ts index 34ad10fdb..278342177 100755 --- a/src/containers/thread/BlogsThread/styles/index.ts +++ b/src/containers/thread/BlogsThread/styles/index.ts @@ -23,7 +23,6 @@ export const RightPart = styled.div` min-width: 200px; max-width: 200px; padding-top: 20px; - margin-left: 40px; ${css.media.tablet`display: none;`}; ` diff --git a/src/containers/thread/JobsThread/index.tsx b/src/containers/thread/JobsThread/index.tsx index fc37bf334..db755f17c 100755 --- a/src/containers/thread/JobsThread/index.tsx +++ b/src/containers/thread/JobsThread/index.tsx @@ -110,11 +110,7 @@ const JobsThreadContainer: FC<TProps> = ({ jobsThread: store }) => { <RightPart> <PublishNote show={showPublishNote} /> <PublisherWrapper> - <PublishButton - label="招贤纳士" - labelIconSrc={`${ICON_CMD}/look_sb.svg`} - onPublish={onContentCreate} - /> + <PublishButton onCreate={onContentCreate} /> </PublisherWrapper> <Sticky offsetTop={50}> diff --git a/src/containers/thread/PostsThread/index.tsx b/src/containers/thread/PostsThread/index.tsx index cba4425a0..425e95c95 100755 --- a/src/containers/thread/PostsThread/index.tsx +++ b/src/containers/thread/PostsThread/index.tsx @@ -6,33 +6,24 @@ import { FC } from 'react' import { Waypoint } from 'react-waypoint' -import { contains } from 'ramda' -import { ICON } from '@/config' -import { C11N, THREAD, ROUTE } from '@/constant' +import { C11N, THREAD } from '@/constant' import { pluggedIn, buildLog } from '@/utils' -import CommunityJoinBadge from '@/containers/tool/CommunityJoinBadge' -import TagsBar from '@/containers/unit/TagsBar' - -import Sticky from '@/components/Sticky' -import { DropdownButton } from '@/components/Buttons' -import Maybe from '@/components/Maybe' +import ThreadSidebar from '@/containers/thread/ThreadSidebar' +import TabBar from '@/components/TabBar' import FaqPeekList from '@/components/FaqPeekList' import PagedContents from '@/components/PagedContents' import ContentFilter from '@/components/ContentFilter' -import ConstructingThread from '@/components/ConstructingThread' -import PromotionList from '@/components/PromotionList' import type { TStore } from './store' import { Wrapper, - LeftPart, - RightPart, + Body, + ArticlesWrapper, + TabsWrapper, FilterWrapper, - BadgeWrapper, - PublisherWrapper, } from './styles' import { @@ -44,9 +35,9 @@ import { onPreview, onPageChange, onFaqChange, + tabOnChange, onContentCreate, onTagSelect, - onAdsClose, } from './logic' /* eslint-disable-next-line */ @@ -65,7 +56,6 @@ const PostsThreadContainer: FC<TProps> = ({ postsThread: store }) => { filtersData, activePost, faqActive, - curRoute, accountInfo, isLogin, activeTagData, @@ -75,88 +65,64 @@ const PostsThreadContainer: FC<TProps> = ({ postsThread: store }) => { accountInfo: { customization: { bannerLayout }, }, - isCommunityDigestInViewport, } = store - const { subPath } = curRoute const { totalCount } = pagedPostsData return ( <Wrapper> - <LeftPart> - <Waypoint onEnter={inAnchor} onLeave={outAnchor} /> - <Maybe test={showFilterBar}> - <FilterWrapper> - <ContentFilter - thread={THREAD.POST} - onSelect={onFilterSelect} - activeFilter={filtersData} - isLogin={isLogin} - accountInfo={accountInfo} - totalCount={totalCount} - faqActive={faqActive} - onFaqChange={onFaqChange} - /> - </FilterWrapper> - </Maybe> - <FaqPeekList active={faqActive} /> - <PagedContents - data={pagedPostsData} - community={curCommunity.raw} - thread={THREAD.POST} - curView={curView} - active={activePost} - accountInfo={accountInfo} - onUserSelect={onUserSelect} - onAuthorSelect={onUserSelect} - onPreview={onPreview} - onPageChange={onPageChange} - /> - </LeftPart> - - {bannerLayout === C11N.DIGEST && ( - <RightPart> - <PublisherWrapper show={isCommunityDigestInViewport}> - <DropdownButton - placement="bottom-end" - options={[ - { - key: 'publish', - icon: `${ICON}/edit/publish-write.svg`, - title: '发布帖子', - desc: '发布后会第一次出现在相应版块首页。', - }, - { - key: 'link', - link: 'https://newpage', - icon: `${ICON}/article/report.svg`, - title: '发布须知', - desc: - '请确保你发布的内容符合社区的基本价值观和规范,否则会被限流或直接删除。', - }, - ]} - panelMinWidth="210px" - onClick={(key) => { - if (key === 'publish') onContentCreate() - }} - > - 发布帖子 - </DropdownButton> - </PublisherWrapper> - - <Sticky offsetTop={55}> - <BadgeWrapper show={!isCommunityDigestInViewport}> - <CommunityJoinBadge /> - </BadgeWrapper> - <TagsBar - thread={THREAD.POST} - onSelect={onTagSelect} - active={activeTagData} - /> - <PromotionList onClose={onAdsClose} /> - </Sticky> - </RightPart> + {bannerLayout === C11N.HOLY_GRAIL && ( + <TabsWrapper> + <TabBar + source={curCommunity.threads} + onChange={tabOnChange} + active={curThread} + layout={C11N.HOLY_GRAIL} + communityRaw={curCommunity.raw} + /> + </TabsWrapper> )} + + <Body> + <ArticlesWrapper> + <Waypoint onEnter={inAnchor} onLeave={outAnchor} /> + {showFilterBar && ( + <FilterWrapper> + <ContentFilter + thread={THREAD.POST} + onSelect={onFilterSelect} + activeFilter={filtersData} + isLogin={isLogin} + accountInfo={accountInfo} + totalCount={totalCount} + faqActive={faqActive} + onFaqChange={onFaqChange} + /> + </FilterWrapper> + )} + <FaqPeekList active={faqActive} /> + <PagedContents + data={pagedPostsData} + community={curCommunity.raw} + thread={THREAD.POST} + curView={curView} + active={activePost} + accountInfo={accountInfo} + onUserSelect={onUserSelect} + onAuthorSelect={onUserSelect} + onPreview={onPreview} + onPageChange={onPageChange} + /> + </ArticlesWrapper> + + {bannerLayout === C11N.CLASSIC && ( + <ThreadSidebar + activeTag={activeTagData} + onCreate={onContentCreate} + onTagSelect={onTagSelect} + /> + )} + </Body> </Wrapper> ) } diff --git a/src/containers/thread/PostsThread/logic.ts b/src/containers/thread/PostsThread/logic.ts index d0a7c0d93..32891c1f9 100755 --- a/src/containers/thread/PostsThread/logic.ts +++ b/src/containers/thread/PostsThread/logic.ts @@ -1,7 +1,7 @@ import { pickBy } from 'ramda' import { useEffect } from 'react' -import type { TTag } from '@/spec' +import type { TTag, TThread } from '@/spec' import { TYPE, EVENT, ERR, THREAD } from '@/constant' import { @@ -11,6 +11,7 @@ import { notEmpty, errRescue, scrollToTabber, + thread2Subpath, } from '@/utils' import type { TStore } from './store' @@ -43,6 +44,17 @@ export const outAnchor = (): void => { if (store) store.showTopModeline(true) } +export const tabOnChange = (activeThread: TThread): void => { + const subPath = thread2Subpath(activeThread) + // log('EVENT.activeThread -----> ', activeThread) + // log('EVENT.subPath -----> ', subPath) + + store.markRoute({ subPath }) + store.setViewing({ activeThread }) + + send(EVENT.THREAD_CHANGE, { data: { activeThread } }) +} + export const loadPosts = (page = 1): void => { const { curCommunity } = store diff --git a/src/containers/thread/PostsThread/store.ts b/src/containers/thread/PostsThread/store.ts index ca7ad90d8..483535007 100755 --- a/src/containers/thread/PostsThread/store.ts +++ b/src/containers/thread/PostsThread/store.ts @@ -87,10 +87,6 @@ const PostsThreadStore = T.model('PostsThreadStore', { return !isEmpty(curFilter) || !isEmpty(pagedPosts.entries) }, - get isCommunityDigestInViewport(): boolean { - const root = getParent(self) as TRootStore - return root.communityDigest.inViewport - }, })) .actions((self) => ({ toastInfo(options): void { diff --git a/src/containers/thread/PostsThread/styles/index.ts b/src/containers/thread/PostsThread/styles/index.ts index 72f342172..c6509ea63 100755 --- a/src/containers/thread/PostsThread/styles/index.ts +++ b/src/containers/thread/PostsThread/styles/index.ts @@ -4,10 +4,22 @@ import type { TActive } from '@/spec' import { css, theme } from '@/utils' export const Wrapper = styled.div` + ${css.flexColumn()}; + width: 100%; +` +export const Body = styled.div` ${css.flex()}; width: 100%; ` -export const LeftPart = styled.div` +export const TabsWrapper = styled.div` + width: calc(100% - 42px); + background: #103645; + padding-left: 20px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + margin-top: 10px; +` +export const ArticlesWrapper = styled.div` flex-grow: 1; width: 100%; background: ${theme('content.bg')}; @@ -16,12 +28,12 @@ export const LeftPart = styled.div` padding-top: 15px; padding-left: 25px; padding-right: 24px; + margin-right: 42px; ` -export const RightPart = styled.div` +export const SidebarWrapper = styled.div` min-width: 200px; max-width: 200px; padding-top: 20px; - margin-left: 40px; ${css.media.tablet`display: none;`}; ` @@ -35,6 +47,10 @@ export const BadgeWrapper = styled.div<TActive>` display: ${({ show }) => (show ? 'block' : 'none')}; margin-left: 18px; ` +export const TagsBarWrapper = styled.div` + margin-top: 20px; + margin-left: 12px; +` export const FilterWrapper = styled.div` ${css.flex('align-center')}; margin-bottom: 10px; diff --git a/src/containers/thread/ThreadSidebar/ClassicView.tsx b/src/containers/thread/ThreadSidebar/ClassicView.tsx new file mode 100644 index 000000000..522511a4a --- /dev/null +++ b/src/containers/thread/ThreadSidebar/ClassicView.tsx @@ -0,0 +1,65 @@ +/* + * + * ClassicSidebar + * common sidebar include community badge, publisher, tagsbar ads .. etc, + * used for classic layout + * + */ + +import { FC } from 'react' + +import { THREAD } from '@/constant' +import { buildLog } from '@/utils' + +import CommunityJoinBadge from '@/containers/tool/CommunityJoinBadge' +import TagsBar from '@/containers/unit/TagsBar' + +import Sticky from '@/components/Sticky' +import { PublishButton } from '@/components/Buttons' +import PromotionList from '@/components/PromotionList' + +import type { TBaseProps } from './index' + +import { + Wrapper, + BadgeWrapper, + TagsBarWrapper, + PublishWrapper, +} from './styles/classic_view' + +/* eslint-disable-next-line */ +const log = buildLog('c:ClassicSidebar') + +type TProps = { showCommunityBadge: boolean } & TBaseProps + +const ClassicView: FC<TProps> = ({ + showCommunityBadge, + activeTag, + onCreate, + onTagSelect, + onAdsClose, +}) => { + return ( + <Wrapper testid="thread-sidebar"> + <PublishWrapper show={showCommunityBadge}> + <PublishButton onCreate={() => onCreate()} /> + </PublishWrapper> + + <Sticky offsetTop={55}> + <BadgeWrapper show={!showCommunityBadge}> + <CommunityJoinBadge /> + </BadgeWrapper> + <TagsBarWrapper> + <TagsBar + thread={THREAD.POST} + onSelect={onTagSelect} + active={activeTag} + /> + </TagsBarWrapper> + <PromotionList onClose={onAdsClose} /> + </Sticky> + </Wrapper> + ) +} + +export default ClassicView diff --git a/src/containers/thread/ThreadSidebar/HolyGrailView/CommunityBrief.tsx b/src/containers/thread/ThreadSidebar/HolyGrailView/CommunityBrief.tsx new file mode 100644 index 000000000..f4896ed1d --- /dev/null +++ b/src/containers/thread/ThreadSidebar/HolyGrailView/CommunityBrief.tsx @@ -0,0 +1,51 @@ +import { FC, memo } from 'react' +import { contains } from 'ramda' + +import type { TCommunity } from '@/spec' +import { NON_FILL_COMMUNITY } from '@/constant' + +import { FollowButton } from '@/components/Buttons' +import SocialList from '@/components/SocialList' + +import { + Wrapper, + Header, + Logo, + CommunityInfo, + TitleWrapper, + TitleText, +} from '../styles/holy_grail_view/community_brief' + +type TProps = { + community: TCommunity +} + +const CommunityBrief: FC<TProps> = ({ community }) => { + return ( + <Wrapper> + <Header> + <Logo + noFill={contains(community.raw, NON_FILL_COMMUNITY)} + src={community.logo} + raw={community.raw} + /> + <FollowButton + hasFollowed + userId="todo" + onFollow={console.log} + onUndoFollow={console.log} + size="tiny" + noBorderWhenFollowed + /> + </Header> + <CommunityInfo> + <TitleWrapper> + <TitleText>{community.title}</TitleText> + </TitleWrapper> + <SocialList size="small" /> + </CommunityInfo> + </Wrapper> + ) +} + +export default memo(CommunityBrief) diff --git a/src/containers/thread/ThreadSidebar/HolyGrailView/ExtraInfo.tsx b/src/containers/thread/ThreadSidebar/HolyGrailView/ExtraInfo.tsx new file mode 100644 index 000000000..ceb8aaf7b --- /dev/null +++ b/src/containers/thread/ThreadSidebar/HolyGrailView/ExtraInfo.tsx @@ -0,0 +1,41 @@ +import { FC, memo } from 'react' + +import TeamList from './TeamList' + +import { + Wrapper, + Item, + Number, + OnlineDesc, + OnlineDot, + Desc, +} from '../styles/holy_grail_view/subscribe_info' + +const ExtraInfo: FC = () => { + return ( + <Wrapper> + <Item> + <Number>1025</Number> + <Desc>关注者</Desc> + </Item> + <Item> + <TeamList /> + <Desc>团队成员</Desc> + </Item> + + {/* <Item> + <Number>25</Number> + <OnlineDesc> + <OnlineDot /> + 在线 + </OnlineDesc> + </Item> + <Item> + <Number>13</Number> + <Desc>志愿者</Desc> + </Item> */} + </Wrapper> + ) +} + +export default memo(ExtraInfo) diff --git a/src/containers/digest/CommunityDigest/DigestView/RowView/TeamList.js b/src/containers/thread/ThreadSidebar/HolyGrailView/TeamList.tsx similarity index 76% rename from src/containers/digest/CommunityDigest/DigestView/RowView/TeamList.js rename to src/containers/thread/ThreadSidebar/HolyGrailView/TeamList.tsx index 415064cbc..ee391b772 100644 --- a/src/containers/digest/CommunityDigest/DigestView/RowView/TeamList.js +++ b/src/containers/thread/ThreadSidebar/HolyGrailView/TeamList.tsx @@ -1,6 +1,6 @@ -import React from 'react' +import { FC, memo } from 'react' -import { Wrapper, Avatar } from '../../styles/digest_view/row_view/team_list' +import { Wrapper, Avatar } from '../styles/holy_grail_view/team_list' const items = [ { @@ -17,7 +17,7 @@ const items = [ }, ] -const TeamList = () => { +const TeamList: FC = () => { return ( <Wrapper> {items.map((item, index) => ( @@ -28,4 +28,4 @@ const TeamList = () => { ) } -export default TeamList +export default memo(TeamList) diff --git a/src/containers/thread/ThreadSidebar/HolyGrailView/index.tsx b/src/containers/thread/ThreadSidebar/HolyGrailView/index.tsx new file mode 100644 index 000000000..dc97d67ed --- /dev/null +++ b/src/containers/thread/ThreadSidebar/HolyGrailView/index.tsx @@ -0,0 +1,38 @@ +import { FC, memo } from 'react' + +import type { TCommunity } from '@/spec' +import { THREAD } from '@/constant' + +import { Br } from '@/components/Common' +import Sticky from '@/components/Sticky' +import TagsBar from '@/containers/unit/TagsBar' +import { PublishButton } from '@/components/Buttons' + +import CommunityBrief from './CommunityBrief' +import ExtraInfo from './ExtraInfo' + +import { Wrapper, Divider } from '../styles/holy_grail_view' + +// 没有各种外链接,打赏信息等的官方社区 + +type TProps = { + community: TCommunity +} + +const HolyGrailView: FC<TProps> = ({ community }) => { + return ( + <Wrapper testid="community-digest"> + <CommunityBrief community={community} /> + <Divider /> + <ExtraInfo /> + <Br bottom={20} /> + <PublishButton /> + <Br bottom={25} /> + <Sticky offsetTop={80}> + <TagsBar thread={THREAD.POST} onSelect={console.log} /> + </Sticky> + </Wrapper> + ) +} + +export default memo(HolyGrailView) diff --git a/src/containers/thread/ThreadSidebar/index.tsx b/src/containers/thread/ThreadSidebar/index.tsx new file mode 100755 index 000000000..8d0d0dc9b --- /dev/null +++ b/src/containers/thread/ThreadSidebar/index.tsx @@ -0,0 +1,68 @@ +// + +/* + * + * ThreadSidebar + * + */ + +import { FC, Fragment } from 'react' + +import type { TTag, TC11NLayout } from '@/spec' +import { C11N } from '@/constant' +import { pluggedIn, buildLog } from '@/utils' + +import ClassicView from './ClassicView' +import HolyGrailView from './HolyGrailView' + +import type { TStore } from './store' +import { useInit } from './logic' + +/* eslint-disable-next-line */ +const log = buildLog('C:ThreadSidebar') + +export type TBaseProps = { + activeTag: TTag + + onCreate?: () => void + onTagSelect?: (tag: TTag) => void + onAdsClose?: () => void +} + +export type TProps = { threadSidebar?: TStore } & TBaseProps + +const ThreadSidebarContainer: FC<TProps> = ({ + threadSidebar: store, + activeTag, + onCreate, + onTagSelect, + onAdsClose, +}) => { + useInit(store) + + const { + accountInfo: { + customization: { bannerLayout }, + }, + curCommunity, + isCommunityDigestInViewport, + } = store + + return ( + <Fragment> + {bannerLayout === C11N.CLASSIC ? ( + <ClassicView + showCommunityBadge={isCommunityDigestInViewport} + activeTag={activeTag} + onCreate={onCreate} + onTagSelect={onTagSelect} + onAdsClose={onAdsClose} + /> + ) : ( + <HolyGrailView community={curCommunity} /> + )} + </Fragment> + ) +} + +export default pluggedIn(ThreadSidebarContainer) as FC<TProps> diff --git a/src/containers/thread/ThreadSidebar/logic.ts b/src/containers/thread/ThreadSidebar/logic.ts new file mode 100755 index 000000000..7d57af351 --- /dev/null +++ b/src/containers/thread/ThreadSidebar/logic.ts @@ -0,0 +1,28 @@ +import { useEffect } from 'react' +// import { } from 'ramda' + +import { buildLog } from '@/utils' + +// import S from './service' +import type { TStore } from './store' + +let store: TStore | undefined + +/* eslint-disable-next-line */ +const log = buildLog('L:ThreadSidebar') + +export const someMethod = (): void => { + // +} + +// ############################### +// init & uninit handlers +// ############################### + +export const useInit = (_store: TStore): void => { + useEffect(() => { + store = _store + log('useInit: ', store) + // return () => store.reset() + }, [_store]) +} diff --git a/src/containers/thread/ThreadSidebar/schema.ts b/src/containers/thread/ThreadSidebar/schema.ts new file mode 100755 index 000000000..0035db982 --- /dev/null +++ b/src/containers/thread/ThreadSidebar/schema.ts @@ -0,0 +1,23 @@ +import gql from 'graphql-tag' + +const simpleMutation = gql` + mutation($id: ID!) { + post(id: $id) { + id + } + } +` +const simpleQuery = gql` + query($filter: filter!) { + post(id: $id) { + id + } + } +` + +const schema = { + simpleMutation, + simpleQuery, +} + +export default schema diff --git a/src/containers/thread/ThreadSidebar/store.ts b/src/containers/thread/ThreadSidebar/store.ts new file mode 100755 index 000000000..9e1fbdac8 --- /dev/null +++ b/src/containers/thread/ThreadSidebar/store.ts @@ -0,0 +1,47 @@ +/* + * ThreadSidebar store + */ + +import { types as T, getParent, Instance } from 'mobx-state-tree' +// import {} from 'ramda' + +import type { TAccount, TCommunity, TThread, TRootStore } from '@/spec' +import { markStates, buildLog, stripMobx } from '@/utils' + +/* eslint-disable-next-line */ +const log = buildLog('S:ThreadSidebar') + +const ThreadSidebar = T.model('ThreadSidebar', { + descExpand: T.optional(T.boolean, false), +}) + .views((self) => ({ + get accountInfo(): TAccount { + const root = getParent(self) as TRootStore + return root.accountInfo + }, + + get curCommunity(): TCommunity { + const root = getParent(self) as TRootStore + + return stripMobx(root.viewing.community) + }, + + get curThread(): TThread { + const root = getParent(self) as TRootStore + return root.viewing.activeThread + }, + + get isCommunityDigestInViewport(): boolean { + const root = getParent(self) as TRootStore + return root.communityDigest.inViewport + }, + })) + .actions((self) => ({ + mark(sobj: Record<string, unknown>): void { + markStates(sobj, self) + }, + })) + +export type TStore = Instance<typeof ThreadSidebar> + +export default ThreadSidebar diff --git a/src/containers/thread/ThreadSidebar/styles/classic_view.ts b/src/containers/thread/ThreadSidebar/styles/classic_view.ts new file mode 100644 index 000000000..b1579f900 --- /dev/null +++ b/src/containers/thread/ThreadSidebar/styles/classic_view.ts @@ -0,0 +1,28 @@ +import styled from 'styled-components' + +import type { TActive, TTestable } from '@/spec' +import { css } from '@/utils' + +export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ + 'data-test-id': testid, +}))<TTestable>` + min-width: 200px; + max-width: 200px; + padding-top: 20px; + + ${css.media.tablet`display: none;`}; +` +export const PublishWrapper = styled.div<TActive>` + display: ${({ show }) => (show ? 'block' : 'none')}; + width: 160px; + max-width: 180px; + margin-left: 16px; +` +export const BadgeWrapper = styled.div<TActive>` + display: ${({ show }) => (show ? 'block' : 'none')}; + margin-left: 18px; +` +export const TagsBarWrapper = styled.div` + margin-top: 20px; + margin-left: 12px; +` diff --git a/src/containers/thread/ThreadSidebar/styles/holy_grail_view/community_brief.ts b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/community_brief.ts new file mode 100644 index 000000000..e26282c02 --- /dev/null +++ b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/community_brief.ts @@ -0,0 +1,47 @@ +import styled from 'styled-components' + +import { theme, css } from '@/utils' + +import Img from '@/Img' +import CommunityFaceLogo from '@/components/CommunityFaceLogo' + +export const Wrapper = styled.div` + ${css.flexColumn('align-start', 'justify-center')}; + width: 100%; + transition: all 0.5s; + margin-top: 18px; + margin-bottom: 5px; +` +export const Header = styled.div` + ${css.flex('align-center', 'justify-between')}; + width: 100%; +` +export const Logo = styled(CommunityFaceLogo)` + ${css.size(35)}; + margin-right: 12px; + border-radius: 5px; +` +export const CommunityInfo = styled.div` + ${css.flexColumn('justify-center')}; + margin-top: 12px; +` +export const TitleWrapper = styled.div` + ${css.flex('align-center')}; + margin-bottom: 8px; +` +export const TitleText = styled.span` + font-size: 18px; + ${css.cutRest('140px')}; + color: ${theme('banner.title')}; +` +export const LogoHolder = styled(Img)` + fill: ${theme('banner.desc')}; + width: 50px; + height: 50px; + @media (max-height: 800px) { + width: 40px; + height: 40px; + } + opacity: 0.6; + margin-top: 3px; +` diff --git a/src/containers/thread/ThreadSidebar/styles/holy_grail_view/index.ts b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/index.ts new file mode 100644 index 000000000..40bcaf85f --- /dev/null +++ b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/index.ts @@ -0,0 +1,21 @@ +import styled from 'styled-components' + +import type { TTestable } from '@/spec' +import { css } from '@/utils' + +export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ + 'data-test-id': testid, +}))<TTestable>` + ${css.flexColumn('justify-start')}; + background: transparent; + position: relative; + width: 150px; + margin-top: 10px; +` +export const Divider = styled.div` + width: 100%; + height: 1px; + background: #014758; + margin-top: 15px; + margin-bottom: 15px; +` diff --git a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/subscribe_info.ts b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/subscribe_info.ts similarity index 63% rename from src/containers/digest/CommunityDigest/styles/digest_view/row_view/subscribe_info.ts rename to src/containers/thread/ThreadSidebar/styles/holy_grail_view/subscribe_info.ts index 178cb4356..90ec564e4 100644 --- a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/subscribe_info.ts +++ b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/subscribe_info.ts @@ -4,28 +4,38 @@ import { css, theme } from '@/utils' import Img from '@/Img' export const Wrapper = styled.div` + ${css.flex('justify-between')}; width: 100%; ` export const Item = styled.div` - ${css.flex('align-center', 'justify-between')}; + ${css.flexColumn('align-start', 'justify-between')}; margin-bottom: 5px; ` export const StateItem = styled.div` - ${css.flex('align-center')}; + ${css.flexColumn('align-start')}; ` -export const Icon = styled(Img)` - fill: ${theme('banner.desc')}; - ${css.size(15)}; +export const Number = styled.div` + font-size: 16px; + color: #139c9e; + margin-bottom: 5px; +` +export const Desc = styled.span` + color: ${theme('banner.desc')}; + font-size: 12px; +` +export const OnlineDesc = styled.div` + ${css.flex('align-center')}; + font-size: 12px; + margin-left: -10px; ` export const OnlineDot = styled.div` - ${css.size(8)}; + ${css.size(4)}; margin-right: 3px; margin-left: 3px; border-radius: 50%; background: ${theme('baseColor.green')}; ` -export const Desc = styled.span` - color: ${theme('banner.desc')}; - font-size: 14px; - margin-left: 10px; +export const Icon = styled(Img)` + fill: ${theme('banner.desc')}; + ${css.size(15)}; ` diff --git a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/team_list.ts b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/team_list.ts similarity index 61% rename from src/containers/digest/CommunityDigest/styles/digest_view/row_view/team_list.ts rename to src/containers/thread/ThreadSidebar/styles/holy_grail_view/team_list.ts index 2620f4ed1..bd1cab63f 100644 --- a/src/containers/digest/CommunityDigest/styles/digest_view/row_view/team_list.ts +++ b/src/containers/thread/ThreadSidebar/styles/holy_grail_view/team_list.ts @@ -7,12 +7,11 @@ import Img from '@/Img' export const Wrapper = styled.div` ${css.flex()}; width: 100%; - flex-wrap: wrap; - margin-bottom: 35px; - margin-top: 10px; + margin-top: 3px; + margin-bottom: 10px; ` export const Avatar = styled(Img)` - ${css.circle(26)}; - margin-right: 12px; - margin-bottom: 15px; + ${css.size(16)}; + margin-right: 6px; + border-radius: 3px; ` diff --git a/src/containers/thread/ThreadSidebar/tests/index.test.js b/src/containers/thread/ThreadSidebar/tests/index.test.js new file mode 100755 index 000000000..45967e28b --- /dev/null +++ b/src/containers/thread/ThreadSidebar/tests/index.test.js @@ -0,0 +1,10 @@ +// import React from 'react' +// import { shallow } from 'enzyme' + +// import ThreadSidebar from '../index' + +describe('TODO <ThreadSidebar />', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(true) + }) +}) diff --git a/src/containers/thread/ThreadSidebar/tests/store.test.js b/src/containers/thread/ThreadSidebar/tests/store.test.js new file mode 100755 index 000000000..903c9ad99 --- /dev/null +++ b/src/containers/thread/ThreadSidebar/tests/store.test.js @@ -0,0 +1,10 @@ +/* + * ThreadSidebar store test + * + */ + +// import ThreadSidebar from '../index' + +it('TODO: store test ThreadSidebar', () => { + expect(1 + 1).toBe(2) +}) diff --git a/src/containers/tool/C11NSettingPanel/GeneralSettings.js b/src/containers/tool/C11NSettingPanel/GeneralSettings.js index 30112f582..32d0a0507 100644 --- a/src/containers/tool/C11NSettingPanel/GeneralSettings.js +++ b/src/containers/tool/C11NSettingPanel/GeneralSettings.js @@ -15,7 +15,6 @@ const GeneralSettings = ({ curThread, customization }) => { const { bannerLayout, - contentsLayout, contentDivider, markViewed, displayDensity, @@ -30,18 +29,14 @@ const GeneralSettings = ({ curThread, customization }) => { size="small" items={[ { - value: '上下布局', - key: C11N.DIGEST, + value: '经典布局', + key: C11N.CLASSIC, }, { - value: '左右布局', - key: C11N.DIGEST_ROW, + value: '圣杯布局', + key: C11N.HOLY_GRAIL, dimOnActive: isMobile, }, - { - value: '简洁布局', - key: C11N.BRIEF, - }, ]} activeKey={bannerLayout} onChange={(item) => @@ -52,39 +47,6 @@ const GeneralSettings = ({ curThread, customization }) => { /> <Divider /> - <Title>文章视图 - - 浏览内容时列表的显示方式, 部分板块(如视频,开源项目等)不支持列表视图。 - - - {!contains(curThread, [THREAD.REPO]) ? ( - <> -
- - onC11NChange({ - contentsLayout: item.key, - }) - } - /> - - - ) : ( - - )} - 阅读辅助
在帖子/文章头部显示“阅”标记。 diff --git a/src/containers/unit/Footer/DesktopView/BottomInfo.tsx b/src/containers/unit/Footer/DesktopView/BottomInfo.tsx index 7d6b0c4fc..4ae3cabcc 100755 --- a/src/containers/unit/Footer/DesktopView/BottomInfo.tsx +++ b/src/containers/unit/Footer/DesktopView/BottomInfo.tsx @@ -1,5 +1,6 @@ import { FC, memo } from 'react' +import type { TC11NLayout } from '@/spec' import { ROUTE } from '@/constant' import { @@ -11,12 +12,13 @@ import { type TProps = { metric: string + layout?: TC11NLayout } -const BottomInfo: FC = ({ metric }) => { +const BottomInfo: FC = ({ metric, layout }) => { return ( - + Groupher @ 2021. 保留所有权利。 diff --git a/src/containers/unit/Footer/DesktopView/DigestView/index.tsx b/src/containers/unit/Footer/DesktopView/DigestView/index.tsx index d4dbe4390..0181bb9da 100644 --- a/src/containers/unit/Footer/DesktopView/DigestView/index.tsx +++ b/src/containers/unit/Footer/DesktopView/DigestView/index.tsx @@ -1,7 +1,7 @@ import { FC, memo } from 'react' import { useTheme } from 'styled-components' -import type { TThemeMap } from '@/spec' +import type { TThemeMap, TC11NLayout } from '@/spec' import { GITHUB, API_SERVER_ADDR, ISSUE_ADDR, BUILD_VERSION } from '@/config' import { ROUTE } from '@/constant' @@ -22,9 +22,10 @@ import { type TProps = { metric: string + layout: TC11NLayout } -const DigestView: FC = ({ metric }) => { +const DigestView: FC = ({ metric, layout }) => { const theme = useTheme() as TThemeMap const linkColors = { @@ -160,7 +161,7 @@ const DigestView: FC = ({ metric }) => { - + ) } diff --git a/src/containers/unit/Footer/DesktopView/TopInfo/HomeCommunity.tsx b/src/containers/unit/Footer/DesktopView/TopInfo/HomeCommunity.tsx index 0670fddf0..089cd4431 100644 --- a/src/containers/unit/Footer/DesktopView/TopInfo/HomeCommunity.tsx +++ b/src/containers/unit/Footer/DesktopView/TopInfo/HomeCommunity.tsx @@ -12,7 +12,7 @@ import { type TProps = Pick -const HomeCommunity: FC = ({ title = 'CoderPlanets' }) => { +const HomeCommunity: FC = ({ title = 'oderPlanets' }) => { return ( diff --git a/src/containers/unit/Footer/DesktopView/index.tsx b/src/containers/unit/Footer/DesktopView/index.tsx index 68330d8a4..8fcf3ad19 100644 --- a/src/containers/unit/Footer/DesktopView/index.tsx +++ b/src/containers/unit/Footer/DesktopView/index.tsx @@ -81,7 +81,7 @@ const FooterContainer: FC = ({ footer: store, metric }) => { /> {curView === 'DIGEST' ? ( - + ) : ( ` ${css.flex('align-center', 'justify-between')}; @@ -16,11 +18,13 @@ export const Wrapper = styled.div<{ metric: string }>` ${css.media.tablet`display: none;`}; ` -export const InnerWrapper = styled.div` +export const InnerWrapper = styled.div<{ layout: TC11NLayout }>` ${css.flexColumn('justify-start')}; color: ${theme('thread.articleDigest')}; width: 100%; margin-right: 20px; + + ${({ layout }) => (layout === C11N.CLASSIC ? 'padding-left: 20px;' : '')}; ` export const BeianLink = styled.a` color: ${theme('footer.text')}; diff --git a/src/containers/unit/Footer/styles/desktop_view/digest_view/index.ts b/src/containers/unit/Footer/styles/desktop_view/digest_view/index.ts index d0fc3df4f..512b31121 100644 --- a/src/containers/unit/Footer/styles/desktop_view/digest_view/index.ts +++ b/src/containers/unit/Footer/styles/desktop_view/digest_view/index.ts @@ -14,6 +14,8 @@ export const Wrapper = styled.footer` export const InnerWrapper = styled.div<{ metric: string }>` width: 100%; ${({ metric }) => css.fitContentWidth(metric)}; + // 20 是经典布局为缩小帖子列表"视觉宽度"手动缩小的值 + padding: 0 20px; ` export const MainInfos = styled.div` ${css.flex('justify-between')}; diff --git a/src/containers/unit/Footer/styles/desktop_view/top_info/index.ts b/src/containers/unit/Footer/styles/desktop_view/top_info/index.ts index db2f97db4..472ddd824 100644 --- a/src/containers/unit/Footer/styles/desktop_view/top_info/index.ts +++ b/src/containers/unit/Footer/styles/desktop_view/top_info/index.ts @@ -20,9 +20,8 @@ export const InfoBar = styled.div` margin-top: 3px; ` export const Logo = styled(CommunityFaceLogo)` - ${css.size(22)}; - margin-right: 12px; - margin-top: -5px; + ${css.size(18)}; + margin-top: -6px; margin-left: 2px; cursor: pointer; ` @@ -30,7 +29,9 @@ export const SiteTitle = styled.div` color: #007fa8; font-size: 18px; font-weight: bold; - margin-right: 25px; + margin-left: 4px; + margin-right: 56px; + letter-spacing: 1px; ` export const ArrowDividerIcon = styled(Img)` fill: ${theme('footer.text')}; diff --git a/src/containers/unit/Footer/styles/index.ts b/src/containers/unit/Footer/styles/index.ts index 9d2738d89..a3b257acc 100755 --- a/src/containers/unit/Footer/styles/index.ts +++ b/src/containers/unit/Footer/styles/index.ts @@ -1,15 +1,15 @@ import styled from 'styled-components' -import type { TTestable } from '@/spec' +import type { TTestable, TC11NLayout } from '@/spec' import { C11N } from '@/constant' import { css } from '@/utils' -type TWrapper = TTestable & { metric: string; layout: string } +type TWrapper = TTestable & { metric: string; layout: TC11NLayout } export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ 'data-test-id': testid, }))` ${css.flex('justify-center')}; - margin-top: ${({ layout }) => (layout === C11N.DIGEST_ROW ? '50px' : '80px')}; + margin-top: ${({ layout }) => (layout === C11N.HOLY_GRAIL ? '50px' : '80px')}; ${({ metric }) => css.fitPageWidth(metric)}; ` export const Holder = 1 diff --git a/src/containers/unit/Header/DesktopView/ArticleEditorView.tsx b/src/containers/unit/Header/DesktopView/ArticleEditorView.tsx index 16ce68c26..2bf050249 100644 --- a/src/containers/unit/Header/DesktopView/ArticleEditorView.tsx +++ b/src/containers/unit/Header/DesktopView/ArticleEditorView.tsx @@ -4,7 +4,7 @@ * */ -import React, { FC, useEffect } from 'react' +import { FC, useEffect } from 'react' import dynamic from 'next/dynamic' import { ICON } from '@/config' @@ -59,7 +59,7 @@ const ArticleEditorHeader: FC = ({ header: store, metric }) => { = ({ header: store, metric }) => { = ({ leftOffset={leftOffset} noBorder={hasNoBottomBorder} > - + ({ margin-left: ${({ leftOffset }) => leftOffset}; box-shadow: ${({ noBorder }) => (noBorder ? 'none' : theme('drawer.shadow'))}; ` -export const InnerWrapper = styled.div<{ metric: string }>` +type TInnerWrapper = { metric: string; layout: TC11NLayout } +export const InnerWrapper = styled.div` ${css.flex('align-center')}; padding: 0 4px; width: 100%; height: 33px; ${({ metric }) => css.fitContentWidth(metric)}; + padding-left: ${({ layout }) => + layout === C11N.CLASSIC ? pixelAdd(WIDTH.COMMUNITY.CONTENT_OFFSET, 10) : 0}; + padding-right: ${({ layout }) => + layout === C11N.CLASSIC ? WIDTH.COMMUNITY.CONTENT_OFFSET : 0}; + ${({ layout }) => (layout === C11N.HOLY_GRAIL ? 'margin-left: 18px' : '')}; ` export const RouterWrapper = styled.div` ${css.flexGrow('align-center')}; diff --git a/src/containers/unit/ModeLine/styles/metrics/top_bar.js b/src/containers/unit/ModeLine/styles/metrics/top_bar.js index b6c0750ea..b6f1d0e8b 100644 --- a/src/containers/unit/ModeLine/styles/metrics/top_bar.js +++ b/src/containers/unit/ModeLine/styles/metrics/top_bar.js @@ -20,7 +20,7 @@ export const getPadding = (type, layout) => { } default: { - return layout === C11N.DIGEST_ROW ? '0 5vw;' : '0 6vw;' + return layout === C11N.HOLY_GRAIL ? '0 5vw;' : '0 6vw;' } } } diff --git a/src/containers/unit/TagsBar/CardView.tsx b/src/containers/unit/TagsBar/CardView.tsx deleted file mode 100644 index 045395143..000000000 --- a/src/containers/unit/TagsBar/CardView.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * TagsBar - * - */ - -import { FC } from 'react' - -import { ICON_CMD } from '@/config' -import { buildLog, pluggedIn, sortByColor, Trans } from '@/utils' - -import type { TProps as TTagProps } from './index' -import { - Wrapper, - TagItem, - TagDot, - TagTitle, - AllTagIcon, -} from './styles/card_view' - -import { useInit, onTagSelect } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:TagsBar') - -type TProps = Omit - -const TagsBarContainer: FC = ({ - tagsBar: store, - thread, - active, - onSelect, -}) => { - useInit(store, thread, active) - - const { tagsData, activeTagData } = store - - const sortedTags = sortByColor(tagsData) - const emptytag = { id: '', title: '', color: '' } - - return ( - - {activeTagData.title && ( - { - onTagSelect(emptytag) - onSelect(emptytag) - }} - > - - 全部 - - )} - - {sortedTags.map(({ id, color, title }) => ( - { - onTagSelect(emptytag) - onSelect(emptytag) - }} - > - - {Trans(title)} - - ))} - - ) -} - -export default pluggedIn(TagsBarContainer) as FC diff --git a/src/containers/unit/TagsBar/index.tsx b/src/containers/unit/TagsBar/index.tsx index 65a11758f..e7ec42659 100755 --- a/src/containers/unit/TagsBar/index.tsx +++ b/src/containers/unit/TagsBar/index.tsx @@ -11,14 +11,13 @@ import type { TTag, TThread } from '@/spec' import type { TStore } from './store' import DesktopView from './DesktopView/index' -import CardView from './CardView' export type TProps = { view?: string tagsBar?: TStore thread: TThread onSelect: (tag?: TTag) => void - active: TTag + active?: TTag } const TagsBar: FC = (props) => { @@ -30,9 +29,9 @@ const TagsBar: FC = (props) => { return } - case VIEW.COMMUNITY_CARD: { - return - } + // case VIEW.COMMUNITY_CARD: { + // return + // } default: { return diff --git a/src/containers/unit/TagsBar/logic.ts b/src/containers/unit/TagsBar/logic.ts index c819754ff..f92d953bb 100755 --- a/src/containers/unit/TagsBar/logic.ts +++ b/src/containers/unit/TagsBar/logic.ts @@ -98,7 +98,7 @@ export const useInit = ( store = _store log('effect init') sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) - let activeTag = pick(['id', 'title', 'color'], active) + let activeTag = pick(['id', 'title', 'color'], active || {}) if (isEmpty(activeTag.title)) activeTag = null store.mark({ thread, activeTag }) diff --git a/src/containers/unit/TagsBar/styles/card_view.ts b/src/containers/unit/TagsBar/styles/card_view.ts deleted file mode 100644 index 0832a3548..000000000 --- a/src/containers/unit/TagsBar/styles/card_view.ts +++ /dev/null @@ -1,58 +0,0 @@ -import styled from 'styled-components' - -import type { TActive } from '@/spec' -import Img from '@/Img' -import { theme, css } from '@/utils' - -type TTagDot = TActive & { title: string; color: string } - -export const Wrapper = styled.div` - ${css.flex()}; - flex-wrap: wrap; -` -export const TagItem = styled.div` - ${css.flex('align-center')}; - min-width: 33%; - margin-bottom: 10px; -` -export const AllTagIcon = styled(Img)` - fill: ${theme('banner.desc')}; - margin-right: 10px; - margin-top: 2px; - ${css.size(14)}; -` -const getDotBgColor = (active, title, color) => { - if (!active) return color - return active === title ? color : 'lightgrey' -} - -export const TagDot = styled.div` - ${css.circle(9)}; - - margin-right: 8px; - background-color: ${({ active, title, color }) => - getDotBgColor(active, title, color)}; - opacity: ${theme('tags.dotOpacity')}; -` -// ${props => (props.active === props.title ? 1 : 0.7)} - -export const TagTitle = styled.div` - flex-grow: 1; - color: ${theme('tags.text')}; - font-size: 14px; - opacity: 0.9; - letter-spacing: 0.1rem; - - &:hover { - cursor: pointer; - opacity: 1; - font-weight: bold; - } - transition: all 0.2s; -` -export const TagOptionsWrapper = styled.div` - display: none; - ${TagItem}:hover & { - display: block; - } -` diff --git a/src/containers/unit/TagsBar/styles/desktop_view/index.ts b/src/containers/unit/TagsBar/styles/desktop_view/index.ts index 8265478ef..ae11cf9d6 100755 --- a/src/containers/unit/TagsBar/styles/desktop_view/index.ts +++ b/src/containers/unit/TagsBar/styles/desktop_view/index.ts @@ -5,7 +5,5 @@ import { css } from '@/utils' export const Wrapper = styled.div` position: relative; ${css.flexColumn()}; - margin-top: 30px; - margin-left: 12px; ` export const TagsWrapper = styled.div`` diff --git a/src/containers/user/UserSettings/index.js b/src/containers/user/UserSettings/index.js index 07b305438..14a342837 100755 --- a/src/containers/user/UserSettings/index.js +++ b/src/containers/user/UserSettings/index.js @@ -51,7 +51,7 @@ const UserSettingsContainer = ({ userSettings: store }) => { items={[ { value: '详细视图', - key: C11N.DIGEST, + key: C11N.CLASSIC, }, { value: '简洁视图', @@ -62,27 +62,6 @@ const UserSettingsContainer = ({ userSettings: store }) => { onChange={(item) => c11nOnChange('bannerLayout', item.key)} /> - - - c11nOnChange('contentsLayout', item.key)} - /> - { errorCode={errorCode} errorPath={community.raw} > - + {/* */} + {/* */} ) diff --git a/src/schemas/fragments/base.ts b/src/schemas/fragments/base.ts index 495cb959c..e177f22dc 100755 --- a/src/schemas/fragments/base.ts +++ b/src/schemas/fragments/base.ts @@ -99,7 +99,6 @@ export const user = ` ` export const c11n = ` bannerLayout - contentsLayout contentDivider markViewed displayDensity diff --git a/src/spec/account.ts b/src/spec/account.ts index b58834872..5127994bb 100644 --- a/src/spec/account.ts +++ b/src/spec/account.ts @@ -1,4 +1,5 @@ import type { TPagedCommunities } from './community' +import type { TC11NLayout } from './c11n' export type TUser = { id?: string @@ -14,8 +15,7 @@ export type TUser = { export type TAccount = TUser & { customization?: { theme?: string - bannerLayout?: string - contentsLayout?: string // oneOf([C11N.DIGEST, C11N.LIST]) + bannerLayout?: TC11NLayout markViewed?: boolean contentDivider?: boolean displayDensity?: string // oneOf(['20', '25', '30']) diff --git a/src/spec/c11n.ts b/src/spec/c11n.ts new file mode 100644 index 000000000..5103df19e --- /dev/null +++ b/src/spec/c11n.ts @@ -0,0 +1,2 @@ +export type TC11NLayout = 'digest' | 'digest_row' +export type holder = string diff --git a/src/spec/index.ts b/src/spec/index.ts index c6139a39b..8ced5dd83 100644 --- a/src/spec/index.ts +++ b/src/spec/index.ts @@ -16,6 +16,7 @@ export type { export type { TButton, TFiltersMenuItems } from './comp' export type { TTheme, TThemeMap, TThemeName } from './theme' export type { TAccount, TUser, TMembership } from './account' +export type { TC11NLayout } from './c11n' export type { TCommunity, TPagedCommunities, TTag } from './community' export type { diff --git a/src/stores/AccountStore/index.ts b/src/stores/AccountStore/index.ts index 899db5ed9..ce0abff47 100755 --- a/src/stores/AccountStore/index.ts +++ b/src/stores/AccountStore/index.ts @@ -25,8 +25,10 @@ const AccountStore = T.model('AccountStore', { }) .views((self) => ({ get accountInfo(): TAccount { + const user = stripMobx(self.user) + return { - ...stripMobx(self.user), + ...user, isLogin: self.isValidSession, isValidSession: self.isValidSession, } diff --git a/src/stores/RootStore/index.ts b/src/stores/RootStore/index.ts index 62864660e..e0c8fee8a 100755 --- a/src/stores/RootStore/index.ts +++ b/src/stores/RootStore/index.ts @@ -92,6 +92,7 @@ import { CoolGuideContentStore, // GEN: IMPORT SUBSTORE + ThreadSidebarStore, BlogsThreadStore, AbuseReportStore, HelpCenterContentStore, @@ -207,6 +208,7 @@ const rootStore = T.model({ coolGuideContent: T.optional(CoolGuideContentStore, {}), // GEN: PLUG SUBSTORE TO ROOTSTORE + threadSidebar: T.optional(ThreadSidebarStore, {}), blogsThread: T.optional(BlogsThreadStore, {}), abuseReport: T.optional(AbuseReportStore, {}), helpCenterContent: T.optional(HelpCenterContentStore, {}), diff --git a/src/stores/SharedModel/User.ts b/src/stores/SharedModel/User.ts index b00756c09..b22924d55 100755 --- a/src/stores/SharedModel/User.ts +++ b/src/stores/SharedModel/User.ts @@ -63,12 +63,9 @@ export const Achievement = T.model('Achievement', { const Customization = T.model('Customization', { bannerLayout: T.optional( - T.enumeration('contentsLayout', [C11N.DIGEST, C11N.DIGEST_ROW, C11N.BRIEF]), - C11N.DIGEST, - ), - contentsLayout: T.optional( - T.enumeration('contentsLayout', [C11N.DIGEST, C11N.LIST]), - C11N.DIGEST, + T.enumeration('bannerLayout', [C11N.CLASSIC, C11N.HOLY_GRAIL, C11N.BRIEF]), + C11N.CLASSIC, + // C11N.HOLY_GRAIL, ), contentDivider: T.optional(T.boolean, false), markViewed: T.optional(T.boolean, true), diff --git a/src/stores/ViewingStore/index.ts b/src/stores/ViewingStore/index.ts index 55a7885fd..342599cd8 100755 --- a/src/stores/ViewingStore/index.ts +++ b/src/stores/ViewingStore/index.ts @@ -58,6 +58,8 @@ const ViewingStore = T.model('ViewingStore', { return stripMobx(self.blog) case THREAD.REPO: return stripMobx(self.repo) + case THREAD.POST: + return stripMobx(self.post) default: return stripMobx(self.post) } diff --git a/src/stores/index.ts b/src/stores/index.ts index ac2918dbb..44fda233a 100755 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -99,6 +99,7 @@ export { default as CommunityEditorStore } from '@/containers/editor/CommunityEd export { default as WorksEditorStore } from '@/containers/editor/WorksEditor/store' // GEN: EXPORT CONTAINERS STORE HERE +export { default as ThreadSidebarStore } from '@/containers/thread/ThreadSidebar/store' export { default as BlogsThreadStore } from '@/containers/thread/BlogsThread/store' export { default as AbuseReportStore } from '@/containers/tool/AbuseReport/store' export { default as HelpCenterContentStore } from '@/containers/content/HelpCenterContent/store' diff --git a/utils/constant/c11n.ts b/utils/constant/c11n.ts index 344154309..6efb91fe1 100755 --- a/utils/constant/c11n.ts +++ b/utils/constant/c11n.ts @@ -1,15 +1,8 @@ const C11N = { - DIGEST: 'digest', - DIGEST_ROW: 'digest_row', + CLASSIC: 'digest', + HOLY_GRAIL: 'digest_row', LIST: 'list', BRIEF: 'brief', - - // TODO: refactor - COMMUNITY_LAYOUT: { - COLUMN: 'column', // default - COLUMN_BRIEF: 'column_brief', - ROW: 'row', - }, } export default C11N diff --git a/utils/constant/view.ts b/utils/constant/view.ts index 336d7b09a..57b486b99 100644 --- a/utils/constant/view.ts +++ b/utils/constant/view.ts @@ -1,7 +1,6 @@ const VIEW = { DESKTOP: 'desktop', MOBILE: 'mobile', - COMMUNITY_CARD: 'COMMUNITY_CARD', MODELINE: 'MODELINE', DRAWER: 'DRAWER', } diff --git a/utils/css/media.ts b/utils/css/media.ts index 4eb853603..b9ad2b360 100644 --- a/utils/css/media.ts +++ b/utils/css/media.ts @@ -21,8 +21,9 @@ export const mediaBreakPoints = { export const WIDTH = { COMMUNITY: { PAGE: '1460px', - CONTENT: '998px', + CONTENT: '1024px', CONTENT_OFFSET: '34px', + LAPTOP_M_PADDING: '44px', }, USER: { PAGE: '1200px', @@ -110,15 +111,15 @@ export const fitContentWidth = (metric = METRIC.COMMUNITY): string => { const laptopMmediaQuery = media.laptopM` padding-left: ${getLaptopMPadding(metric)}; padding-right: ${getLaptopMPadding(metric)}; - ` // .join('') + ` const desktopLmediaQuery = media.desktopL` margin-left: ${WIDTH[metric]?.CONTENT_OFFSET_DESKTOPL}; - ` // .join('') + ` const laptopLmediaQuery = media.laptopL` margin-left: ${WIDTH[metric]?.CONTENT_OFFSET_LAPTOPL}; - ` // .join('') + ` return ` max-width: ${getContentMaxWidth(metric)};