diff --git a/.eslintignore b/.eslintignore index 20fdcbf38..b980bf2d1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ .gitignore *.json *.lock -*.hbs \ No newline at end of file +*.hbs +*.svg \ No newline at end of file diff --git a/public/icons/static/shape/image.svg b/public/icons/static/shape/image.svg new file mode 100644 index 000000000..403eed857 --- /dev/null +++ b/public/icons/static/shape/image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/static/shape/video.svg b/public/icons/static/shape/video.svg new file mode 100644 index 000000000..5e2a58fb6 --- /dev/null +++ b/public/icons/static/shape/video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/AvatarsRow/MoreItem.js b/src/components/AvatarsRow/MoreItem.tsx similarity index 66% rename from src/components/AvatarsRow/MoreItem.js rename to src/components/AvatarsRow/MoreItem.tsx index 883ca9dbc..58b9110f4 100644 --- a/src/components/AvatarsRow/MoreItem.js +++ b/src/components/AvatarsRow/MoreItem.tsx @@ -1,8 +1,10 @@ -import React, { useCallback } from 'react' +import React from 'react' import { prettyNum } from '@/utils' import Tooltip from '@/components/Tooltip' +import type { TProps as TAvatarsProps } from './index' + import { Wrapper, NumbersMore, @@ -12,13 +14,19 @@ import { Focus, } from './styles/more_item' -const MoreItem = ({ users, size, total, onTotalSelect, showTotalNumber }) => { - const handleClick = useCallback(() => { - onTotalSelect({ users, total }) - }, [onTotalSelect, total, users]) +type TProps = Pick< + TAvatarsProps, + 'size' | 'total' | 'showTotalNumber' | 'onTotalSelect' +> +const MoreItem: React.FC = ({ + size, + total, + onTotalSelect, + showTotalNumber, +}) => { return ( - + onTotalSelect()}> { ) } - duration={0} > {showTotalNumber ? ( - + ... ) : ( diff --git a/src/components/AvatarsRow/index.js b/src/components/AvatarsRow/index.tsx similarity index 58% rename from src/components/AvatarsRow/index.js rename to src/components/AvatarsRow/index.tsx index 1c4879ca1..3130597b0 100755 --- a/src/components/AvatarsRow/index.js +++ b/src/components/AvatarsRow/index.tsx @@ -4,16 +4,17 @@ * */ -import React, { useCallback } from 'react' -import T from 'prop-types' -import { compose, not, isNil, filter, reverse, slice } from 'ramda' +import React from 'react' +import { compose, not, isNil, filter, reverse as reverseFn, slice } from 'ramda' import { trackWindowScroll } from 'react-lazy-load-image-component' +import type { TUser } from '@/spec' import { AVATARS_LIST_LENGTH } from '@/config' import { SIZE } from '@/constant' -import { buildLog, o2s, s2o } from '@/utils' +import { buildLog } from '@/utils' import Tooltip from '@/components/Tooltip' +import type { TAvatarSize } from './spec' import MoreItem from './MoreItem' @@ -45,41 +46,46 @@ const getUniqueArray = (arr, comp) => { return unique } -const AvatarsRow = ({ +export type TProps = { + users?: TUser[] + size?: TAvatarSize + total: number + limit: number + showTotalNumber?: boolean + reverse?: boolean + scrollPosition?: any + + onUserSelect: (user: TUser) => void + onTotalSelect: () => void +} + +const AvatarsRow: React.FC = ({ + size = SIZE.SMALL, total, - users, - size, - limit, - onUserSelect, - onTotalSelect, - showTotalNumber, - reverse: isReverse, - scrollPosition, + users = [], + limit = AVATARS_LIST_LENGTH.POSTS, + onUserSelect = log, + onTotalSelect = log, + showTotalNumber = false, + reverse = true, + // see https://github.com/Aljullu/react-lazy-load-image-component/issues/42 + scrollPosition = null, }) => { - const handleUserSelect = useCallback( - (e) => { - const user = s2o(e.target.dataset.user) - onUserSelect(user) - }, - [onUserSelect], - ) - if (users.length === 0) { return } users = filter(validUser, getUniqueArray(users, 'id')) - const sortedUsers = isReverse ? users : reverse(users) + const sortedUsers = reverse ? users : reverseFn(users) return ( - + {total <= 1 ? ( ) : ( @@ -91,18 +97,18 @@ const AvatarsRow = ({ content={user.nickname} duration={0} delay={300} - contentHeight={getAvatarSize(size)} + contentHeight={getAvatarSize(size, 'number') as string} + noPadding > onUserSelect(user)} scrollPosition={scrollPosition} fallback={ } @@ -114,35 +120,4 @@ const AvatarsRow = ({ ) } -AvatarsRow.propTypes = { - users: T.arrayOf( - T.shape({ - id: T.string, - avatar: T.string, - nickname: T.string, - extra_id: T.string, - }), - ), - size: T.oneOf([SIZE.SMALL, SIZE.MEDIUM]), - total: T.number.isRequired, - limit: T.number, - onUserSelect: T.func, - onTotalSelect: T.func, - showTotalNumber: T.bool, - reverse: T.bool, - scrollPosition: T.any, -} - -AvatarsRow.defaultProps = { - size: SIZE.SMALL, - users: [], - limit: AVATARS_LIST_LENGTH.POSTS, - onUserSelect: log, - onTotalSelect: log, - showTotalNumber: false, - reverse: true, - // see https://github.com/Aljullu/react-lazy-load-image-component/issues/42 - scrollPosition: null, -} - export default trackWindowScroll(AvatarsRow) diff --git a/src/components/AvatarsRow/spec.ts b/src/components/AvatarsRow/spec.ts new file mode 100644 index 000000000..f8349bbf2 --- /dev/null +++ b/src/components/AvatarsRow/spec.ts @@ -0,0 +1,3 @@ +import type { TSIZE_SM } from '@/spec' + +export type TAvatarSize = TSIZE_SM diff --git a/src/components/AvatarsRow/styles/index.ts b/src/components/AvatarsRow/styles/index.ts index fc1615bee..c9df23140 100755 --- a/src/components/AvatarsRow/styles/index.ts +++ b/src/components/AvatarsRow/styles/index.ts @@ -5,6 +5,7 @@ import { theme, css } from '@/utils' import ImgFallback from '@/components/ImgFallback' import { getLiSize, getAvatarSize, getUlMarginRight } from './metric' +import type { TAvatarSize } from '../spec' export const Wrapper = styled.ul<{ total: number }>` ${css.flex('align-center')}; @@ -15,7 +16,7 @@ export const Wrapper = styled.ul<{ total: number }>` margin-right: ${({ total }) => getUlMarginRight(total)}; ` // height: 49px; -type TBaseAvatarItem = { size: string; noHoverMargin: string } +type TBaseAvatarItem = { size: TAvatarSize; noHoverMargin: boolean } const BaseAvatarItem = styled.li` margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; @@ -45,7 +46,8 @@ export const AvatarsItem = styled(BaseAvatarItem)` export const TotalOneOffset = styled.span` margin-right: 10px; ` -export const AvatarsImg = styled(Img)<{ size: string }>` +type TAvatarsImg = { size: string; onClick: () => void; scrollPosition: any } +export const AvatarsImg = styled(Img)` border: 2px solid; border-color: ${theme('thread.commentsUserBorder')}; border-radius: 100px 100px 100px 100px; @@ -60,7 +62,7 @@ export const AvatarsImg = styled(Img)<{ size: string }>` text-align: center; ` -type TAvatarsMore = { size: string; total: number } +type TAvatarsMore = { size: TAvatarSize; total: number } export const AvatarsMore = styled.span` ${css.flex('align-both')}; font-size: 14px; diff --git a/src/components/AvatarsRow/styles/metric.ts b/src/components/AvatarsRow/styles/metric.ts index e2150fe61..5883d011a 100644 --- a/src/components/AvatarsRow/styles/metric.ts +++ b/src/components/AvatarsRow/styles/metric.ts @@ -1,9 +1,11 @@ import { SIZE } from '@/constant' +import type { TAvatarSize } from '../spec' + /** * NOTE: Li size should always smaller than the avatar size */ -export const getLiSize = (size: string): string => { +export const getLiSize = (size: TAvatarSize): string => { switch (size) { case SIZE.SMALL: { return '15px' diff --git a/src/components/DigestSentence/index.js b/src/components/DigestSentence/index.js deleted file mode 100755 index 4d1d7d9b3..000000000 --- a/src/components/DigestSentence/index.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * DigestSentence - * - */ - -import React from 'react' -import T from 'prop-types' - -import { ICON } from '@/config' -import { buildLog } from '@/utils' - -import { Wrapper, PreviewWrapper, PreviewText, PreviewIcon } from './styles' - -/* eslint-disable-next-line */ -const log = buildLog('c:DigestSentence:index') - -const DigestSentence = ({ - testid, - children, - onPreview, - top, - bottom, - left, - right, -}) => { - return ( - - {children} - - 预览 - - - - ) -} - -DigestSentence.propTypes = { - testid: T.string, - children: T.oneOfType([T.string, T.node]), - onPreview: T.func, - top: T.number, - bottom: T.number, - left: T.number, - right: T.number, -} - -DigestSentence.defaultProps = { - testid: 'digest-sentence', - children: '可能是最性感的开发者社区,来为你心爱的作品建立...', - onPreview: log, - top: 0, - bottom: 0, - left: 0, - right: 0, -} - -export default React.memo(DigestSentence) diff --git a/src/components/DigestSentence/index.tsx b/src/components/DigestSentence/index.tsx new file mode 100755 index 000000000..08e71196a --- /dev/null +++ b/src/components/DigestSentence/index.tsx @@ -0,0 +1,73 @@ +/* + * + * DigestSentence + * + */ + +import React from 'react' + +import { ICON } from '@/config' +import { buildLog } from '@/utils' + +import { Space } from '@/components/Common' + +import { + Wrapper, + MediaHintWrapper, + HintIcon, + HintText, + PreviewWrapper, + PreviewText, + PreviewIcon, +} from './styles' + +/* eslint-disable-next-line */ +const log = buildLog('c:DigestSentence:index') + +type TProps = { + testid?: string + children: React.ReactNode + onPreview: () => void + top?: number + bottom?: number + left?: number + right?: number +} + +const DigestSentence: React.FC = ({ + testid = 'digest-sentence', + children = '可能是最性感的开发者社区,来为你心爱的作品建立...', + onPreview = log, + top = 0, + bottom = 0, + left = 0, + right = 0, +}) => { + return ( + + {children} + + + + 3 + + + + 1 + + + 预览 + + + + ) +} + +export default React.memo(DigestSentence) diff --git a/src/components/DigestSentence/styles/index.ts b/src/components/DigestSentence/styles/index.ts index 31f5f3170..a8d928af1 100755 --- a/src/components/DigestSentence/styles/index.ts +++ b/src/components/DigestSentence/styles/index.ts @@ -22,6 +22,27 @@ export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ transition: color 0.2s; ` +export const MediaHintWrapper = styled.div` + position: relative; + margin-left: 5px; + display: inline-flex; +` +export const HintIcon = styled(Img)` + position: absolute; + top: 1px; + left: 0; + fill: ${theme('thread.articleDigest')}; + ${css.size(14)}; + margin-right: 3px; +` +export const HintText = styled.div` + color: ${theme('thread.articleTitle')}; + font-size: 11px; + height: 12px; + margin-right: 5px; + padding-left: 17px; +` + export const PreviewWrapper = styled.div` display: inline-flex; opacity: 0; diff --git a/src/components/PostItem/DigestView/DesktopView/ActiveBadge.tsx b/src/components/PostItem/DigestView/DesktopView/ActiveBadge.tsx new file mode 100644 index 000000000..b9a5f93bb --- /dev/null +++ b/src/components/PostItem/DigestView/DesktopView/ActiveBadge.tsx @@ -0,0 +1,41 @@ +import React from 'react' + +import type { TPost } from '@/spec' +import { ICON } from '@/config' + +import Tooltip from '@/components/Tooltip' + +import { + Wrapper, + PopContent, + PopContentDate, + ItemInner, + Icon, +} from '../../styles/digest_view/active_badge' + +type TProps = { + item: TPost +} + +const ActiveBadge: React.FC = ({ item }) => { + return ( + 0}> + +
最后回复
2020-03-11 + + } + placement="bottom" + noPadding + > + + + 4天前 + +
+
+ ) +} + +export default ActiveBadge diff --git a/src/components/PostItem/DigestView/DesktopView/Body.js b/src/components/PostItem/DigestView/DesktopView/Body.tsx similarity index 73% rename from src/components/PostItem/DigestView/DesktopView/Body.js rename to src/components/PostItem/DigestView/DesktopView/Body.tsx index 725e3ce7b..8499c48f6 100644 --- a/src/components/PostItem/DigestView/DesktopView/Body.js +++ b/src/components/PostItem/DigestView/DesktopView/Body.tsx @@ -1,13 +1,15 @@ import React from 'react' import TimeAgo from 'timeago-react' +import type { TPost } from '@/spec' import { ICON } from '@/config' import { cutRest } from '@/utils' -import Tooltip from '@/components/Tooltip' import { SpaceGrow } from '@/components/Common' import DigestSentence from '@/components/DigestSentence' +import ActiveBadge from './ActiveBadge' + import { Wrapper, Dot, @@ -17,11 +19,14 @@ import { AuthorName, ItemWrapper, ViewsIcon, - ActiveItemWrapper, - ActiveIcon, } from '../../styles/digest_view/body' -const Body = ({ item, onPreview }) => { +type TProps = { + item: TPost + onPreview?: (obj: TPost) => void +} + +const Body: React.FC = ({ item, onPreview }) => { return ( @@ -39,12 +44,7 @@ const Body = ({ item, onPreview }) => { - 0}> - 最后回复} placement="bottom"> - - - 4天前 - + onPreview(item)}> diff --git a/src/components/PostItem/DigestView/DesktopView/Header.js b/src/components/PostItem/DigestView/DesktopView/Header.tsx similarity index 85% rename from src/components/PostItem/DigestView/DesktopView/Header.js rename to src/components/PostItem/DigestView/DesktopView/Header.tsx index 75ebef315..d50407a29 100644 --- a/src/components/PostItem/DigestView/DesktopView/Header.js +++ b/src/components/PostItem/DigestView/DesktopView/Header.tsx @@ -1,6 +1,7 @@ import React from 'react' import Link from 'next/link' +import type { TPost, TUser } from '@/spec' import { ROUTE } from '@/constant' import { ICON_CMD } from '@/config' import { parseDomain } from '@/utils' @@ -17,7 +18,12 @@ import { TagListWrapper, } from '../../styles/digest_view/header' -const Header = ({ item, onUserSelect }) => { +type TProps = { + item: TPost + onUserSelect?: (obj: TUser) => void +} + +const Header: React.FC = ({ item, onUserSelect }) => { return ( diff --git a/src/components/PostItem/DigestView/DesktopView/index.js b/src/components/PostItem/DigestView/DesktopView/index.tsx similarity index 66% rename from src/components/PostItem/DigestView/DesktopView/index.js rename to src/components/PostItem/DigestView/DesktopView/index.tsx index 4d87d5bdc..f088c29fd 100644 --- a/src/components/PostItem/DigestView/DesktopView/index.js +++ b/src/components/PostItem/DigestView/DesktopView/index.tsx @@ -1,5 +1,6 @@ import React from 'react' +import type { TPost, TUser, TAccount } from '@/spec' import { ICON_BASE } from '@/config' import TheAvatar from '@/components/TheAvatar' @@ -9,10 +10,19 @@ import Body from './Body' import { Avatar, Main } from '../../styles/digest_view/index' -const DigestView = ({ +type TProps = { + active?: TPost | null + entry: TPost + cover: 'avatar' | 'source' + + onPreview?: (obj: TPost) => void + onUserSelect?: (obj: TUser) => void + onAuthorSelect?: (obj: TAccount) => void +} + +const DigestView: React.FC = ({ entry, cover, - community, onPreview, onUserSelect, onAuthorSelect, @@ -27,11 +37,7 @@ const DigestView = ({ /> )}
-
+
diff --git a/src/components/PostItem/DigestView/MobileView/Body.js b/src/components/PostItem/DigestView/MobileView/Body.tsx similarity index 77% rename from src/components/PostItem/DigestView/MobileView/Body.js rename to src/components/PostItem/DigestView/MobileView/Body.tsx index 1c903b2c7..d20665e60 100644 --- a/src/components/PostItem/DigestView/MobileView/Body.js +++ b/src/components/PostItem/DigestView/MobileView/Body.tsx @@ -1,5 +1,6 @@ import React from 'react' +import type { TPost } from '@/spec' import { ICON_CMD } from '@/config' import { parseDomain } from '@/utils' @@ -10,7 +11,12 @@ import { Title, } from '../../styles/mobile_view/body' -const Body = ({ item, onPreview }) => { +type TProps = { + item: TPost + onPreview?: (obj: TPost) => void +} + +const Body: React.FC = ({ item, onPreview }) => { return ( onPreview(item)}> {item.title} diff --git a/src/components/PostItem/DigestView/MobileView/Footer.js b/src/components/PostItem/DigestView/MobileView/Footer.tsx similarity index 86% rename from src/components/PostItem/DigestView/MobileView/Footer.js rename to src/components/PostItem/DigestView/MobileView/Footer.tsx index 182632d70..29bd501f2 100644 --- a/src/components/PostItem/DigestView/MobileView/Footer.js +++ b/src/components/PostItem/DigestView/MobileView/Footer.tsx @@ -1,5 +1,6 @@ import React from 'react' +import type { TPost } from '@/spec' import { cutRest } from '@/utils' import { ICON_CMD } from '@/config' @@ -14,7 +15,11 @@ import { BodyDigest, } from '../../styles/mobile_view/footer' -const Footer = ({ item }) => { +type TProps = { + item: TPost +} + +const Footer: React.FC = ({ item }) => { return ( diff --git a/src/components/PostItem/DigestView/MobileView/Header.js b/src/components/PostItem/DigestView/MobileView/Header.tsx similarity index 84% rename from src/components/PostItem/DigestView/MobileView/Header.js rename to src/components/PostItem/DigestView/MobileView/Header.tsx index bffe73693..b02bcb56f 100644 --- a/src/components/PostItem/DigestView/MobileView/Header.js +++ b/src/components/PostItem/DigestView/MobileView/Header.tsx @@ -1,6 +1,7 @@ import React from 'react' import TimeAgo from 'timeago-react' +import type { TPost, TAccount } from '@/spec' import { ICON_BASE } from '@/config' import InlineTags from '@/components/InlineTags' @@ -16,7 +17,13 @@ import { TagListWrapper, } from '../../styles/mobile_view/header' -const Header = ({ cover, item, onAuthorSelect }) => { +type TProps = { + item: TPost + cover: 'avatar' | 'source' + onAuthorSelect?: (obj: TAccount) => void +} + +const Header: React.FC = ({ cover, item, onAuthorSelect }) => { return ( diff --git a/src/components/PostItem/DigestView/MobileView/index.js b/src/components/PostItem/DigestView/MobileView/index.tsx similarity index 57% rename from src/components/PostItem/DigestView/MobileView/index.js rename to src/components/PostItem/DigestView/MobileView/index.tsx index c163387f2..5a8886818 100644 --- a/src/components/PostItem/DigestView/MobileView/index.js +++ b/src/components/PostItem/DigestView/MobileView/index.tsx @@ -1,12 +1,28 @@ import React from 'react' +import type { TPost, TAccount } from '@/spec' + import Header from './Header' import Body from './Body' import Footer from './Footer' import { Wrapper } from '../../styles/mobile_view/index' -const MobileView = ({ entry, cover, onPreview, onAuthorSelect }) => { +type TProps = { + entry: TPost + cover: 'avatar' | 'source' + community: string + + onPreview?: (obj: TPost) => void + onAuthorSelect?: (obj: TAccount) => void +} + +const MobileView: React.FC = ({ + entry, + cover, + onPreview, + onAuthorSelect, +}) => { return (
diff --git a/src/components/PostItem/ListView.js b/src/components/PostItem/ListView.tsx similarity index 89% rename from src/components/PostItem/ListView.js rename to src/components/PostItem/ListView.tsx index 2d49124ca..339e9a276 100755 --- a/src/components/PostItem/ListView.js +++ b/src/components/PostItem/ListView.tsx @@ -1,9 +1,10 @@ import React from 'react' import TimeAgo from 'timeago-react' +import type { TPost } from '@/spec' import { ICON_CMD } from '@/config' - import { cutRest, parseDomain } from '@/utils' + import InlineTags from '@/components/InlineTags' import { @@ -21,7 +22,12 @@ import { CommentNum, } from './styles/list_view' -const ListView = ({ entry, onPreview }) => ( +type TProps = { + entry: TPost + onPreview?: (obj: TPost) => void +} + +const ListView: React.FC = ({ entry, onPreview }) => (
diff --git a/src/components/PostItem/index.js b/src/components/PostItem/index.tsx similarity index 52% rename from src/components/PostItem/index.js rename to src/components/PostItem/index.tsx index c38dc5c59..9cd00a856 100755 --- a/src/components/PostItem/index.js +++ b/src/components/PostItem/index.tsx @@ -5,12 +5,13 @@ */ import React from 'react' -import T from 'prop-types' +import type { TPost, TUser, TAccount } from '@/spec' import { HCN, C11N } from '@/constant' import { buildLog } from '@/utils' import ArticleItemPrefixLabel from '@/components/ArticleItemPrefixLabel' + import DigestView from './DigestView/index' import ListView from './ListView' @@ -19,15 +20,35 @@ import { Wrapper } from './styles' /* eslint-disable-next-line */ const log = buildLog('c:PostItem:index') -const PostItem = ({ +type TProps = { + active?: TPost | null + entry: TPost + cover: 'avatar' | 'source' + community: string + accountInfo: TAccount + + onPreview?: (obj: TPost) => void + onUserSelect?: (obj: TUser) => void + onAuthorSelect?: (obj: TAccount) => void +} + +const PostItem: React.FC = ({ entry, - cover, - community, - active, - onPreview, - onUserSelect, - onAuthorSelect, - accountInfo, + onPreview = log, + onUserSelect = log, + onAuthorSelect = log, + active = null, + cover = 'avatar', + community = HCN, + accountInfo = { + isLogin: false, + customization: { + contentsLayout: C11N.DIGEST, + contentDivider: false, + markViewed: true, + displayDensity: '20', + }, + }, }) => { // log('customization --> ', customization) const { @@ -52,63 +73,10 @@ const PostItem = ({ onAuthorSelect={onAuthorSelect} /> ) : ( - + )} ) } -PostItem.propTypes = { - active: T.object, - entry: T.shape({ - title: T.string, - digest: T.string, - views: T.number, - - author: T.shape({ - nickname: T.string, - avatar: T.string, - }), - }).isRequired, - cover: T.oneOf(['avatar', 'source']), - community: T.string, - - 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']), - }), - }), - onPreview: T.func, - onUserSelect: T.func, - onAuthorSelect: T.func, -} - -PostItem.defaultProps = { - onPreview: log, - onUserSelect: log, - onAuthorSelect: log, - active: {}, - cover: 'avatar', - community: HCN, - accountInfo: { - isLogin: false, - customization: T.shape({ - contentsLayout: C11N.DIGEST, - contentDivider: false, - markViewed: true, - displayDensity: '20', - }), - }, -} - export default React.memo(PostItem) diff --git a/src/components/PostItem/styles/digest_view/active_badge.ts b/src/components/PostItem/styles/digest_view/active_badge.ts new file mode 100644 index 000000000..0b57c8ef6 --- /dev/null +++ b/src/components/PostItem/styles/digest_view/active_badge.ts @@ -0,0 +1,41 @@ +import styled from 'styled-components' + +import { theme, css } from '@/utils' +import Img from '@/Img' + +import { Main } from './index' + +export const Wrapper = styled.div<{ hasComments: boolean }>` + ${css.flex('align-center')}; + display: ${({ hasComments }) => (hasComments ? 'flex' : 'none')}; + position: absolute; + top: 3px; + right: 0; + color: ${theme('thread.articleDigest')}; + margin-right: 6px; + margin-top: 8px; + opacity: 0.8; + + ${Main}:hover & { + opacity: 1; + } + transition: opacity 0.2s; +` +export const ItemInner = styled.div` + ${css.flex('align-center')}; +` +export const PopContent = styled.div` + ${css.flexColumn('align-end')}; + width: 100%; + min-width: 85px; + font-size: 12px; +` +export const PopContentDate = styled.div` + margin-top: 6px; +` +export const Icon = styled(Img)` + fill: ${theme('thread.articleDigest')}; + ${css.size(12)}; + opacity: 0.6; + margin-right: 3px; +` diff --git a/src/components/PostItem/styles/digest_view/body.ts b/src/components/PostItem/styles/digest_view/body.ts index a8a068189..6c6070b62 100644 --- a/src/components/PostItem/styles/digest_view/body.ts +++ b/src/components/PostItem/styles/digest_view/body.ts @@ -43,25 +43,3 @@ export const ViewsIcon = styled(Img)` opacity: 0.6; margin-right: 3px; ` - -export const ActiveItemWrapper = styled.div<{ hasComments: string }>` - position: absolute; - top: ${({ hasComments }) => (hasComments ? '5px' : '-24px')}; - right: 0; - ${css.flex('align-center')}; - color: ${theme('thread.articleDigest')}; - margin-right: 6px; - margin-top: 8px; - opacity: 0; - - ${Main}:hover & { - opacity: 1; - } - transition: opacity 0.2s; -` -export const ActiveIcon = styled(Img)` - fill: ${theme('thread.articleDigest')}; - ${css.size(12)}; - opacity: 0.6; - margin-right: 3px; -` diff --git a/src/components/PostItem/styles/index.ts b/src/components/PostItem/styles/index.ts index 3e993c3b3..5a3ddbf44 100755 --- a/src/components/PostItem/styles/index.ts +++ b/src/components/PostItem/styles/index.ts @@ -1,16 +1,18 @@ import styled from 'styled-components' -import type { TActive, TUser } from '@/spec' +import type { TPost, TAccount } from '@/spec' import { theme, css } from '@/utils' import { getOpacity } from './metrics' -type IPostItemUI = TActive & { accountInfo: TUser } & { - entry: any +type TWrapper = { + entry: TPost + active?: TPost | null divider: boolean + accountInfo: TAccount } -export const Wrapper = styled.article` +export const Wrapper = styled.article` ${css.flex()}; position: relative; opacity: ${({ entry, active, accountInfo }) => diff --git a/src/components/PostItem/styles/metrics.ts b/src/components/PostItem/styles/metrics.ts index a48cdd26a..b232f212c 100644 --- a/src/components/PostItem/styles/metrics.ts +++ b/src/components/PostItem/styles/metrics.ts @@ -1,12 +1,18 @@ -export const getOpacity = (entry, active, accountInfo): number => { +import type { TPost, TAccount } from '@/spec' + +export const getOpacity = ( + entry: TPost, + active: TPost | null, + accountInfo: TAccount, +): number => { const { isLogin, customization: { markViewed }, } = accountInfo const { viewerHasViewed } = entry - if (active.id) { - return entry.id !== active.id ? 0.6 : 1 + if (active?.id) { + return entry.id !== active?.id ? 0.6 : 1 } if (isLogin && markViewed && viewerHasViewed) { return 0.85 diff --git a/src/containers/unit/Comments/Comment/Header.tsx b/src/containers/unit/Comments/Comment/Header.tsx index 16aeee7e6..2ba030ebb 100755 --- a/src/containers/unit/Comments/Comment/Header.tsx +++ b/src/containers/unit/Comments/Comment/Header.tsx @@ -24,7 +24,7 @@ const getAuthors = (comment) => { /* eslint-disable no-return-assign */ const replies = forEach((reply) => { /* @ts-ignore */ - return (reply.author.extra_id = reply.id) + return (reply.author.extraId = reply.id) }, clone(comment.replies)) /* eslint-enable */ diff --git a/src/spec/account.ts b/src/spec/account.ts index b8562f7f0..0006da1d8 100644 --- a/src/spec/account.ts +++ b/src/spec/account.ts @@ -1,14 +1,20 @@ export type TUser = { - id: string + id?: string login?: string nickname?: string name?: string - avatar: string + avatar?: string + // TODO: figure it out + extraId?: string } export type TAccount = TUser & { customization?: { - theme: string - bannerLayout: string + theme?: string + bannerLayout?: string + contentsLayout?: string // oneOf([C11N.DIGEST, C11N.LIST]) + markViewed?: boolean + contentDivider?: boolean + displayDensity?: string // oneOf(['20', '25', '30']) } isLogin?: boolean isValidSession?: boolean diff --git a/src/spec/article.ts b/src/spec/article.ts index ff67b3c48..faf614f80 100644 --- a/src/spec/article.ts +++ b/src/spec/article.ts @@ -1,11 +1,12 @@ -import type { TCommunity } from './index' +import type { TCommunity, TTag } from './index' import type { TUser } from './account' export type TArticle = { - id: string - title: string - body: string - author: { + id?: string + title?: string + body?: string + views?: number + author?: { id: string login: string nickname: string @@ -14,7 +15,15 @@ export type TArticle = { origialCommunity?: TCommunity commentsParticipators?: TUser insertedAt?: string - // ... + viewerHasViewed?: boolean + commentsCount?: number + tags?: TTag[] +} + +export type TPost = TArticle & { + digest?: string + linkAddr?: string + linkIcon?: string } export type TJob = { diff --git a/src/spec/index.ts b/src/spec/index.ts index 1e6435622..303c52208 100644 --- a/src/spec/index.ts +++ b/src/spec/index.ts @@ -35,6 +35,7 @@ export type { TGQLError } from './graphql' export type { TArticle, + TPost, TJob, TPagedJobs, TComment, diff --git a/src/spec/size.ts b/src/spec/size.ts index 94802a021..67afb11d4 100644 --- a/src/spec/size.ts +++ b/src/spec/size.ts @@ -7,6 +7,6 @@ export type TSIZE_M = 'medium' export type TSIZE_L = 'large' export type TSIZE_TS = TSIZE_T | TSIZE_S -export type TSIZE_SM = TSIZE_T | TSIZE_M +export type TSIZE_SM = TSIZE_S | TSIZE_M export type TSIZE_TSM = TSIZE_T | TSIZE_S | TSIZE_M export type TSIZE_SML = TSIZE_S | TSIZE_M | TSIZE_L