diff --git a/public/icons/static/article/cc-by.svg b/public/icons/static/article/cc-by.svg
new file mode 100644
index 000000000..211260d5b
--- /dev/null
+++ b/public/icons/static/article/cc-by.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/cc-nc.svg b/public/icons/static/article/cc-nc.svg
new file mode 100644
index 000000000..0db547ce7
--- /dev/null
+++ b/public/icons/static/article/cc-nc.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/cc-nd.svg b/public/icons/static/article/cc-nd.svg
new file mode 100644
index 000000000..a632ac135
--- /dev/null
+++ b/public/icons/static/article/cc-nd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/cc-raw.svg b/public/icons/static/article/cc-raw.svg
new file mode 100644
index 000000000..99b55cc9f
--- /dev/null
+++ b/public/icons/static/article/cc-raw.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/cc.svg b/public/icons/static/article/cc.svg
new file mode 100644
index 000000000..3dfd59cf0
--- /dev/null
+++ b/public/icons/static/article/cc.svg
@@ -0,0 +1,27 @@
+
+
+
+
diff --git a/public/icons/static/article/collect-bookmark.svg b/public/icons/static/article/collect-bookmark.svg
new file mode 100644
index 000000000..c568aa01a
--- /dev/null
+++ b/public/icons/static/article/collect-bookmark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/copyright-approve.svg b/public/icons/static/article/copyright-approve.svg
new file mode 100644
index 000000000..7dd38a7cd
--- /dev/null
+++ b/public/icons/static/article/copyright-approve.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/copyright-forbid.svg b/public/icons/static/article/copyright-forbid.svg
new file mode 100644
index 000000000..a8c511d08
--- /dev/null
+++ b/public/icons/static/article/copyright-forbid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/copyright-printer.svg b/public/icons/static/article/copyright-printer.svg
new file mode 100644
index 000000000..34ea8a5a0
--- /dev/null
+++ b/public/icons/static/article/copyright-printer.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/icons/static/article/copyright.svg b/public/icons/static/article/copyright.svg
new file mode 100644
index 000000000..191dbc07d
--- /dev/null
+++ b/public/icons/static/article/copyright.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/Buttons/IconButton.tsx b/src/components/Buttons/IconButton.tsx
index 87667ab6d..c34b1c8f0 100644
--- a/src/components/Buttons/IconButton.tsx
+++ b/src/components/Buttons/IconButton.tsx
@@ -30,7 +30,7 @@ const IconButton: FC = ({
active = false,
dimWhenIdle = false,
hint = null,
- hintDelay = 1000,
+ hintDelay = 500,
hintPlacement = 'top',
onClick = console.log,
}) => {
diff --git a/src/components/Buttons/styles/arrow_link.ts b/src/components/Buttons/styles/arrow_link.ts
index ff0ba243e..45d00662a 100644
--- a/src/components/Buttons/styles/arrow_link.ts
+++ b/src/components/Buttons/styles/arrow_link.ts
@@ -14,17 +14,17 @@ export const Wrapper = styled.a`
`
type TText = { hoverColor: string; size: string }
export const Text = styled.div`
- color: ${({ color }) => color || theme('thread.articleDigest')};
+ color: ${({ color }) => color || '#327ca1'};
font-size: ${({ size }) => getTextSize(size)};
${Wrapper}:hover & {
- color: ${({ hoverColor }) => hoverColor || theme('thread.articleTitle')};
+ color: ${({ hoverColor }) => hoverColor || '#327ca1'};
visibility: visible;
}
`
type TIcon = { color: string; size: string }
const Icon = styled(Img)`
- fill: ${({ color }) => color || theme('thread.articleDigest')};
+ fill: ${({ color }) => color || '#327ca1'};
width: ${({ size }) => getIconSize(size)};
height: ${({ size }) => getIconSize(size)};
display: block;
@@ -37,7 +37,7 @@ export const RightIcon = styled(Icon)<{ hoverColor: string }>`
visibility: hidden;
${Wrapper}:hover & {
- fill: ${({ hoverColor }) => hoverColor || theme('thread.articleTitle')};
+ fill: ${({ hoverColor }) => hoverColor || '#327ca1'};
margin-left: 10px;
visibility: visible;
}
diff --git a/src/components/Copyright/Label.tsx b/src/components/Copyright/Label.tsx
new file mode 100644
index 000000000..c561d40b1
--- /dev/null
+++ b/src/components/Copyright/Label.tsx
@@ -0,0 +1,41 @@
+import { FC, memo } from 'react'
+
+import { ICON } from '@/config'
+import { Wrapper, Icon, Text } from './styles/label'
+
+type TProps = {
+ type?: 'cc' | 'approve' | 'forbid'
+}
+
+const Label: FC = ({ type }) => {
+ switch (type) {
+ case 'approve': {
+ return (
+
+
+ 转载需授权
+
+ )
+ }
+
+ case 'forbid': {
+ return (
+
+
+ 禁止转载
+
+ )
+ }
+
+ default: {
+ return (
+
+
+ 知识共享 4.0
+
+ )
+ }
+ }
+}
+
+export default memo(Label)
diff --git a/src/components/Copyright/ReadOnlyPanel.tsx b/src/components/Copyright/ReadOnlyPanel.tsx
new file mode 100644
index 000000000..6508ed241
--- /dev/null
+++ b/src/components/Copyright/ReadOnlyPanel.tsx
@@ -0,0 +1,88 @@
+import { FC, memo } from 'react'
+
+import { ICON } from '@/config'
+import { ArrowLink } from '@/components/Buttons'
+
+import {
+ Wrapper,
+ Header,
+ Icon,
+ Title,
+ Desc,
+ Items,
+ DescItem,
+ Footer,
+} from './styles/readonly_panel'
+
+type TProps = {
+ type?: 'cc' | 'approve' | 'forbid'
+}
+
+const ReadOnlyPanel: FC = ({ type }) => {
+ switch (type) {
+ case 'approve': {
+ return (
+
+
+
+ 根据作者设置,转载需获取本人授权。相关联系方式可参考作者主页。
+
+
+ )
+ }
+
+ case 'forbid': {
+ return (
+
+
+
+ 根据作者设置,本文严禁任何方式的转载,如有疑问,请尝试联系作者。
+
+
+ )
+ }
+
+ default: {
+ return (
+
+
+
+
+ 本作品采用知识共享「署名-非商业性使用-禁止演绎 4.0
+ 国际」许可证授权。
+
+
+ 署名
+
+
+ 非商业性使用
+
+
+ 禁止演绎
+
+
+
+
+
+ )
+ }
+ }
+}
+
+export default memo(ReadOnlyPanel)
diff --git a/src/components/Copyright/index.tsx b/src/components/Copyright/index.tsx
new file mode 100755
index 000000000..a14ca87a5
--- /dev/null
+++ b/src/components/Copyright/index.tsx
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright
+ *
+ */
+
+import { FC, memo } from 'react'
+
+import type { TCopyright } from '@/spec'
+import Tooltip from '@/components/Tooltip'
+import { buildLog } from '@/utils'
+
+import Label from './Label'
+import SettingMenu from '@/components/SettingMenu'
+import ReadOnlyPanel from './ReadOnlyPanel'
+import { Wrapper } from './styles'
+
+/* eslint-disable-next-line */
+const log = buildLog('c:Copyright:index')
+
+const options = [
+ {
+ title: '知识共享 4.0',
+ desc: '署名-非商业性使用-禁止演绎',
+ key: 'cc',
+ },
+ {
+ title: '转载需授权',
+ desc: '转载需得到我的明确授权。',
+ key: 'approve',
+ },
+ {
+ title: '禁止转载',
+ desc: '禁止一切形式的转载,有疑问联系我。',
+ key: 'forbid',
+ },
+]
+
+type TProps = {
+ testid?: string
+ type?: TCopyright
+ mode?: 'readonly' | 'editable'
+ onChange?: (type: string) => void
+}
+
+const Copyright: FC = ({
+ testid = 'copyright',
+ type = 'cc',
+ mode = 'readonly',
+ onChange = log,
+}) => {
+ return (
+
+
+ ) : (
+
+ )
+ }
+ placement="top"
+ trigger="click"
+ noPadding
+ >
+
+
+
+ )
+}
+
+export default memo(Copyright)
diff --git a/src/components/Copyright/styles/index.ts b/src/components/Copyright/styles/index.ts
new file mode 100755
index 000000000..82dbbc6f1
--- /dev/null
+++ b/src/components/Copyright/styles/index.ts
@@ -0,0 +1,23 @@
+import styled from 'styled-components'
+
+import type { TTestable } from '@/spec'
+
+import Img from '@/Img'
+import { css, theme } from '@/utils'
+
+export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({
+ 'data-test-id': testid,
+}))``
+
+export const Label = styled.div`
+ ${css.flex('align-center')};
+`
+export const Icon = styled(Img)`
+ ${css.size(14)};
+ fill: ${theme('thread.articleDigest')};
+`
+export const Text = styled.div`
+ font-size: 12px;
+ color: ${theme('thread.articleDigest')};
+ margin-right: 5px;
+`
diff --git a/src/components/Copyright/styles/label.ts b/src/components/Copyright/styles/label.ts
new file mode 100755
index 000000000..d5c3eba51
--- /dev/null
+++ b/src/components/Copyright/styles/label.ts
@@ -0,0 +1,29 @@
+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 Icon = styled(Img)`
+ fill: ${theme('thread.articleDigest')};
+ ${css.size(13)};
+
+ ${Wrapper}:hover & {
+ fill: ${theme('thread.articleTitle')};
+ }
+
+ transition: fill 0.2s;
+`
+export const Text = styled.div`
+ font-size: 13px;
+ color: ${theme('thread.articleDigest')};
+ margin-left: 6px;
+
+ ${Wrapper}:hover & {
+ color: ${theme('thread.articleTitle')};
+ }
+ transition: color 0.2s;
+`
diff --git a/src/components/Copyright/styles/readonly_panel.ts b/src/components/Copyright/styles/readonly_panel.ts
new file mode 100755
index 000000000..e055e97b9
--- /dev/null
+++ b/src/components/Copyright/styles/readonly_panel.ts
@@ -0,0 +1,39 @@
+import styled from 'styled-components'
+import IconText from '@/components/IconText'
+
+import Img from '@/Img'
+import { css, theme } from '@/utils'
+
+export const Wrapper = styled.div`
+ ${css.flexColumn()};
+ width: 240px;
+ padding-left: 5px;
+`
+export const Header = styled.div`
+ ${css.flex('align-center')};
+`
+export const Icon = styled(Img)`
+ ${css.size(18)};
+ fill: ${theme('thread.articleTitle')};
+`
+export const Title = styled.div`
+ font-size: 16px;
+ color: ${theme('thread.articleTitle')};
+ margin-left: 8px;
+`
+export const Desc = styled.div`
+ font-size: 13px;
+ color: ${theme('thread.articleDigest')};
+ margin-top: 8px;
+ margin-bottom: 8px;
+`
+export const Items = styled.div`
+ margin-top: 10px;
+ margin-bottom: 6px;
+`
+export const DescItem = styled(IconText)`
+ margin-bottom: 3px;
+`
+export const Footer = styled.div`
+ ${css.flex('align-center')};
+`
diff --git a/src/components/Copyright/tests/index.test.ts b/src/components/Copyright/tests/index.test.ts
new file mode 100755
index 000000000..53890bb26
--- /dev/null
+++ b/src/components/Copyright/tests/index.test.ts
@@ -0,0 +1,10 @@
+// import React from 'react'
+// import { shallow } from 'enzyme'
+
+// import Copyright from '../index'
+
+describe('TODO ', () => {
+ it('Expect to have unit tests specified', () => {
+ expect(true).toEqual(true)
+ })
+})
diff --git a/src/components/IconText/index.tsx b/src/components/IconText/index.tsx
index aea5babc2..239ea4139 100755
--- a/src/components/IconText/index.tsx
+++ b/src/components/IconText/index.tsx
@@ -7,6 +7,7 @@
import { FC, ReactNode, memo } from 'react'
import type { TSIZE } from '@/spec'
+import { ICON } from '@/config'
import { buildLog, nilOrEmpty } from '@/utils'
import { SIZE } from '@/constant'
@@ -16,26 +17,44 @@ import { Wrapper, Icon, Text } from './styles'
const log = buildLog('c:IconText:index')
type TProps = {
- iconSrc: string
+ iconSrc?: string | null
+ path?: string | null
round?: boolean
children: ReactNode
size?: TSIZE
margin?: string
+ highlight?: boolean
+ className?: string
}
const IconText: FC = ({
- iconSrc,
+ className = '',
+ iconSrc = null,
+ path = null,
round = false,
children,
size = SIZE.SMALL,
margin,
-}) => (
-
- {!nilOrEmpty(iconSrc) && (
-
- )}
- {children}
-
-)
+ highlight = false,
+}) => {
+ const src = iconSrc || `${ICON}/${path}`
+
+ return (
+
+ {!nilOrEmpty(src) && (
+
+ )}
+
+ {children}
+
+
+ )
+}
export default memo(IconText)
diff --git a/src/components/IconText/styles/index.ts b/src/components/IconText/styles/index.ts
index c437d2764..8e7eb61c0 100755
--- a/src/components/IconText/styles/index.ts
+++ b/src/components/IconText/styles/index.ts
@@ -10,6 +10,7 @@ type TIcon = {
size: TSIZE
margin: string
round: boolean
+ highlight: boolean
}
export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({
@@ -18,15 +19,22 @@ export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({
${css.flex('align-center')};
`
export const Icon = styled(Img)`
- fill: ${theme('thread.articleDigest')};
+ fill: ${({ highlight }) =>
+ highlight ? theme('thread.articleTitle') : theme('thread.articleDigest')};
width: ${({ size }) => getIconSize(size)};
height: ${({ size }) => getIconSize(size)};
margin-right: ${({ size, margin }) => margin || getMargin(size)};
display: block;
border-radius: ${({ round }) => (round ? '100%' : '0')};
`
-export const Text = styled.div<{ size: TSIZE }>`
+type TText = {
+ size: TSIZE
+ highlight: boolean
+}
+
+export const Text = styled.div`
${css.flex('align-center')};
- color: ${theme('thread.articleDigest')};
+ color: ${({ highlight }) =>
+ highlight ? theme('thread.articleTitle') : theme('thread.articleDigest')};
font-size: ${({ size }) => getTextSize(size)};
`
diff --git a/src/components/PromotionList/Spotlight.tsx b/src/components/PromotionList/Spotlight.tsx
index 7a3623af7..6267212ae 100755
--- a/src/components/PromotionList/Spotlight.tsx
+++ b/src/components/PromotionList/Spotlight.tsx
@@ -3,10 +3,10 @@ import { FC, memo } from 'react'
import type { TItem } from './spec'
import {
Wrapper,
- ItemWrapper,
Header,
- Logo,
Title,
+ JoinWrapper,
+ JoinNumber,
Desc,
} from './styles/spotlight'
@@ -16,13 +16,14 @@ type TProps = {
const Spotlight: FC = ({ item }) => (
-
-
- {item.desc}
-
+
+ {item.desc}
+
+ 58
+ 人已加入
+
)
diff --git a/src/components/PromotionList/styles/index.ts b/src/components/PromotionList/styles/index.ts
index c2422eae3..00350ba5e 100755
--- a/src/components/PromotionList/styles/index.ts
+++ b/src/components/PromotionList/styles/index.ts
@@ -3,10 +3,10 @@ import styled from 'styled-components'
import { css, theme } from '@/utils'
export const Wrapper = styled.div`
- margin-left: 20px;
+ margin-left: 15px;
min-height: 150px;
max-width: 180px;
- margin-top: 10px;
+ margin-top: 15px;
`
export const Header = styled.div`
${css.flex('justify-between', 'align-center')};
diff --git a/src/components/PromotionList/styles/spotlight.ts b/src/components/PromotionList/styles/spotlight.ts
index 258dde889..e3b512b78 100755
--- a/src/components/PromotionList/styles/spotlight.ts
+++ b/src/components/PromotionList/styles/spotlight.ts
@@ -1,37 +1,36 @@
import styled from 'styled-components'
import { css, theme } from '@/utils'
-import Img from '@/Img'
export const Wrapper = styled.div`
${css.flexColumn()};
background: #06303b;
- padding: 15px 10px;
+ padding: 10px;
width: 100%;
min-height: 120px;
border-radius: 5px;
- margin-left: -5px;
-`
-export const ItemWrapper = styled.div`
- ${css.flexColumn()};
+ margin-left: -8px;
`
export const Header = styled.div`
${css.flex('align-center', 'justify-between')};
margin-left: 2px;
`
-export const Logo = styled(Img)`
- ${css.size(25)};
- border-radius: 5px;
- margin-right: 10px;
- /* TODO: for dark themes */
- filter: saturate(0.8);
-`
export const Title = styled.div`
color: ${theme('thread.articleTitle')};
font-size: 15px;
`
export const Desc = styled.div`
color: ${theme('thread.articleDigest')};
+ flex-grow: 1;
font-size: 12px;
margin-top: 12px;
`
+export const JoinWrapper = styled.div`
+ ${css.flex('align-center')};
+ color: ${theme('thread.articleDigest')};
+ font-size: 12px;
+`
+export const JoinNumber = styled.div`
+ color: ${theme('thread.articleTitle')};
+ margin-right: 3px;
+`
diff --git a/src/components/SettingMenu/index.tsx b/src/components/SettingMenu/index.tsx
new file mode 100755
index 000000000..2214b3140
--- /dev/null
+++ b/src/components/SettingMenu/index.tsx
@@ -0,0 +1,53 @@
+/*
+ *
+ * SettingMenu
+ *
+ */
+
+import { FC, memo } from 'react'
+
+import { buildLog } from '@/utils'
+
+import { Wrapper, Option, ActiveDot, Title, Desc } from './styles'
+
+/* eslint-disable-next-line */
+const log = buildLog('c:SettingMenu:index')
+
+type TProps = {
+ testid?: string
+ width?: number | null
+ activeKey?: string
+ withActive?: boolean
+ options: {
+ title: string
+ desc?: string
+ key: string
+ }[]
+ onChange?: (type: string) => void
+}
+
+const SettingMenu: FC = ({
+ testid = 'setting-menu',
+ options,
+ width = 220,
+ activeKey = null,
+ onChange = log,
+}) => {
+ return (
+
+ {options.map((option) => (
+
+ ))}
+
+ )
+}
+
+export default memo(SettingMenu)
diff --git a/src/components/SettingMenu/styles/index.ts b/src/components/SettingMenu/styles/index.ts
new file mode 100755
index 000000000..5510187f0
--- /dev/null
+++ b/src/components/SettingMenu/styles/index.ts
@@ -0,0 +1,42 @@
+import styled from 'styled-components'
+
+import type { TTestable, TActive } from '@/spec'
+
+// import Img from '@/Img'
+import { css, theme } from '@/utils'
+
+type TWrapper = TTestable & { width: number }
+
+export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({
+ 'data-test-id': testid,
+}))`
+ ${css.flexColumn()};
+ width: ${({ width }) => `${width}px`};
+`
+export const Option = styled.div`
+ position: relative;
+ padding: 10px 15px;
+ padding-left: 40px;
+ background: ${({ $active }) => ($active ? '#0d3b4a' : 'transparent')};
+
+ &:hover {
+ cursor: pointer;
+ background: #0d3b4a;
+ }
+`
+export const ActiveDot = styled.div`
+ ${css.circle(6)};
+ background: #107eae;
+ position: absolute;
+ left: 20px;
+ top: 18px;
+`
+export const Title = styled.div`
+ color: ${theme('thread.articleTitle')};
+ font-size: 15px;
+`
+export const Desc = styled.div`
+ color: ${theme('thread.articleDigest')};
+ font-size: 12px;
+ margin-top: 2px;
+`
diff --git a/src/components/SettingMenu/tests/index.test.ts b/src/components/SettingMenu/tests/index.test.ts
new file mode 100755
index 000000000..8b87ddbc6
--- /dev/null
+++ b/src/components/SettingMenu/tests/index.test.ts
@@ -0,0 +1,10 @@
+// import React from 'react'
+// import { shallow } from 'enzyme'
+
+// import SettingMenu from '../index'
+
+describe('TODO ', () => {
+ it('Expect to have unit tests specified', () => {
+ expect(true).toEqual(true)
+ })
+})
diff --git a/src/components/Tooltip/styles/index.ts b/src/components/Tooltip/styles/index.ts
index f62365c0e..b7c1bc904 100755
--- a/src/components/Tooltip/styles/index.ts
+++ b/src/components/Tooltip/styles/index.ts
@@ -10,6 +10,8 @@ export const StyledTippy = styled(Tippy)`
box-shadow: ${theme('popover.boxShadow')};
outline: none;
max-width: 480px !important;
+ border: 1px solid;
+ border-color: ${theme('popover.borderColor')};
border-radius: 5px;
padding: 10px;
diff --git a/src/containers/unit/ArticleFooter/Actions/ActionItem.js b/src/containers/unit/ArticleFooter/Actions/ActionItem.tsx
similarity index 70%
rename from src/containers/unit/ArticleFooter/Actions/ActionItem.js
rename to src/containers/unit/ArticleFooter/Actions/ActionItem.tsx
index 0df945244..f2dd461ba 100644
--- a/src/containers/unit/ArticleFooter/Actions/ActionItem.js
+++ b/src/containers/unit/ArticleFooter/Actions/ActionItem.tsx
@@ -1,5 +1,6 @@
-import React from 'react'
+import { FC, memo } from 'react'
+import type { TAccount, TArticle, TCommunity } from '@/spec'
import { ICON, ICON_BASE } from '@/config'
import ImgFallback from '@/components/ImgFallback'
@@ -15,7 +16,18 @@ import {
CommunityIcon,
} from '../styles/actions/action_item'
-const ActionItem = ({ item: { author, article, community, insertedAt } }) => {
+type TProps = {
+ item: {
+ author: TAccount
+ article: TArticle
+ community: TCommunity
+ insertedAt: string
+ }
+}
+
+const ActionItem: FC = ({
+ item: { author, article, community, insertedAt },
+}) => {
return (
@@ -37,4 +49,4 @@ const ActionItem = ({ item: { author, article, community, insertedAt } }) => {
)
}
-export default React.memo(ActionItem)
+export default memo(ActionItem)
diff --git a/src/containers/unit/ArticleFooter/Actions/OperationPanel.js b/src/containers/unit/ArticleFooter/Actions/OperationPanel.tsx
similarity index 87%
rename from src/containers/unit/ArticleFooter/Actions/OperationPanel.js
rename to src/containers/unit/ArticleFooter/Actions/OperationPanel.tsx
index 98e99053e..be6cd51c4 100644
--- a/src/containers/unit/ArticleFooter/Actions/OperationPanel.js
+++ b/src/containers/unit/ArticleFooter/Actions/OperationPanel.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import { FC, memo } from 'react'
import { ICON } from '@/config'
@@ -28,7 +28,7 @@ const tmpItems = [
},
]
-const OperationPanel = () => {
+const OperationPanel: FC = () => {
return (
@@ -41,4 +41,4 @@ const OperationPanel = () => {
)
}
-export default React.memo(OperationPanel)
+export default memo(OperationPanel)
diff --git a/src/containers/unit/ArticleFooter/Actions/RefersPanel.js b/src/containers/unit/ArticleFooter/Actions/RefersPanel.tsx
similarity index 91%
rename from src/containers/unit/ArticleFooter/Actions/RefersPanel.js
rename to src/containers/unit/ArticleFooter/Actions/RefersPanel.tsx
index f590a947a..cd5bc15db 100644
--- a/src/containers/unit/ArticleFooter/Actions/RefersPanel.js
+++ b/src/containers/unit/ArticleFooter/Actions/RefersPanel.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import { FC, memo } from 'react'
import { ICON } from '@/config'
@@ -43,7 +43,7 @@ const tmpItems = [
},
]
-const RefersPanel = () => {
+const RefersPanel: FC = () => {
return (
@@ -56,4 +56,4 @@ const RefersPanel = () => {
)
}
-export default React.memo(RefersPanel)
+export default memo(RefersPanel)
diff --git a/src/containers/unit/ArticleFooter/Actions/index.js b/src/containers/unit/ArticleFooter/Actions/index.js
deleted file mode 100644
index 8427d45ff..000000000
--- a/src/containers/unit/ArticleFooter/Actions/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react'
-
-import { ICON } from '@/config'
-import { useDevice } from '@/hooks'
-
-import { Space } from '@/components/Common'
-
-import {
- Wrapper,
- Item,
- ReferIcon,
- RecordIcon,
- ReferNum,
- Text,
-} from '../styles/actions'
-import { toggleActionPanel } from '../logic'
-
-const Actions = ({ showReferenceList, showOperationList }) => {
- const { isMobile } = useDevice()
-
- return (
-
- - toggleActionPanel('reference-list')}>
-
-
- 6
- {!isMobile && 次}
- 引用
-
-
-
- - toggleActionPanel('operation-list')}>
-
-
- 操作
- {!isMobile && 记录}
-
-
-
- )
-}
-
-export default React.memo(Actions)
diff --git a/src/containers/unit/ArticleFooter/Actions/index.tsx b/src/containers/unit/ArticleFooter/Actions/index.tsx
new file mode 100644
index 000000000..eb4eea473
--- /dev/null
+++ b/src/containers/unit/ArticleFooter/Actions/index.tsx
@@ -0,0 +1,39 @@
+import { FC, memo } from 'react'
+
+import { useDevice } from '@/hooks'
+
+import DotDivider from '@/components/DotDivider'
+
+import { Wrapper, Item, ReferNum, Text } from '../styles/actions'
+import { toggleActionPanel } from '../logic'
+
+type TProps = {
+ showReferenceList: boolean
+ showOperationList: boolean
+}
+
+const Actions: FC = ({ showReferenceList, showOperationList }) => {
+ const { isMobile } = useDevice()
+
+ return (
+
+ - toggleActionPanel('reference-list')}>
+
+ 6
+ {!isMobile && 次}
+ 引用
+
+
+
+ - toggleActionPanel('operation-list')}>
+ 日志
+
+
+ -
+ 举报
+
+
+ )
+}
+
+export default memo(Actions)
diff --git a/src/containers/unit/ArticleFooter/AuthorInfo/SocialList.js b/src/containers/unit/ArticleFooter/AuthorInfo/SocialList.js
deleted file mode 100644
index e542b9787..000000000
--- a/src/containers/unit/ArticleFooter/AuthorInfo/SocialList.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from 'react'
-
-import { ICON } from '@/config'
-import { Wrapper, CursorDivider, Icon } from '../styles/author_info/social_list'
-
-const SocialList = ({ items }) => {
- return (
-
-
- {items.map((item) => (
-
- ))}
-
- )
-}
-
-export default React.memo(SocialList)
diff --git a/src/containers/unit/ArticleFooter/AuthorInfo/SocialList.tsx b/src/containers/unit/ArticleFooter/AuthorInfo/SocialList.tsx
new file mode 100644
index 000000000..8b8f18888
--- /dev/null
+++ b/src/containers/unit/ArticleFooter/AuthorInfo/SocialList.tsx
@@ -0,0 +1,22 @@
+import { FC, memo } from 'react'
+import { keys } from 'ramda'
+
+import { ICON } from '@/config'
+import { Wrapper, CursorDivider, Icon } from '../styles/author_info/social_list'
+
+type TProps = {
+ items: Record
+}
+
+const SocialList: FC = ({ items }) => {
+ return (
+
+
+ {keys(items).map((platform) => (
+
+ ))}
+
+ )
+}
+
+export default memo(SocialList)
diff --git a/src/containers/unit/ArticleFooter/AuthorInfo/index.js b/src/containers/unit/ArticleFooter/AuthorInfo/index.tsx
similarity index 54%
rename from src/containers/unit/ArticleFooter/AuthorInfo/index.js
rename to src/containers/unit/ArticleFooter/AuthorInfo/index.tsx
index c6b67e843..d39c78ed7 100644
--- a/src/containers/unit/ArticleFooter/AuthorInfo/index.js
+++ b/src/containers/unit/ArticleFooter/AuthorInfo/index.tsx
@@ -4,10 +4,10 @@
*
*/
-import React from 'react'
-import T from 'prop-types'
+import { FC, memo } from 'react'
import { isEmpty, pickBy } from 'ramda'
+import type { TAccount } from '@/spec'
import { buildLog } from '@/utils'
import { Button } from '@/components/Buttons'
@@ -29,8 +29,16 @@ import {
/* eslint-disable-next-line */
const log = buildLog('c:AuthorInfo:index')
-const AuthorInfo = ({ testid, author }) => {
- const socialItems = pickBy((v) => !!v, author.social)
+type TProps = {
+ testid?: string
+ author: TAccount
+}
+
+const AuthorInfo: FC = ({ testid = 'author-info', author }) => {
+ const socialItems = pickBy((v) => !!v, author.social) as Record<
+ string,
+ string
+ >
return (
@@ -45,7 +53,7 @@ const AuthorInfo = ({ testid, author }) => {
}
+ fallback={}
/>
diff --git a/src/containers/viewer/ArticleViewer/index.tsx b/src/containers/viewer/ArticleViewer/index.tsx
index bc4bb7320..77034f423 100755
--- a/src/containers/viewer/ArticleViewer/index.tsx
+++ b/src/containers/viewer/ArticleViewer/index.tsx
@@ -9,16 +9,17 @@ import { FC } from 'react'
import { pluggedIn, buildLog } from '@/utils'
import Comments from '@/containers/unit/Comments'
+import ArticleFooter from '@/containers/unit/ArticleFooter'
+
// TODO: remove
// import ArticleBodyHeader from '@/containers/unit/ArticleBodyHeader'
// TODO: remove
// import ArticleViewerHeader from '@/containers/unit/ArticleViewerHeader'
-import type { TStore } from './store'
-
import PostViewer from './PostViewer'
-import WorksViewer from './WorksViewer'
+// import WorksViewer from './WorksViewer'
+import type { TStore } from './store'
import { Wrapper, CommentsWrapper } from './styles'
import { useInit } from './logic'
@@ -39,8 +40,9 @@ const ArticleViewerContainer: FC = ({
return (
-
- {/* */}
+ {/* */}
+
+
diff --git a/src/containers/viewer/ArticleViewer/styles/post_viewer/article_info.ts b/src/containers/viewer/ArticleViewer/styles/post_viewer/article_info.ts
index cf275b0d8..ff6492e49 100644
--- a/src/containers/viewer/ArticleViewer/styles/post_viewer/article_info.ts
+++ b/src/containers/viewer/ArticleViewer/styles/post_viewer/article_info.ts
@@ -10,6 +10,30 @@ export const Wrapper = styled.div`
border-bottom: 1px solid;
border-bottom-color: ${theme('drawer.divider')};
`
+export const CollectWrapper = styled.div`
+ ${css.flex('align-center')};
+ cursor: pointer;
+`
+export const CollectIcon = styled(Img)`
+ ${css.size(16)};
+ fill: ${theme('thread.articleDigest')};
+
+ ${CollectWrapper}:hover & {
+ fill: #129497;
+ }
+ transition: fill 0.2s;
+`
+export const CollectText = styled.div`
+ font-size: 14px;
+ color: ${theme('thread.articleDigest')};
+ margin-top: 1px;
+ margin-left: 4px;
+
+ ${CollectWrapper}:hover & {
+ color: #129497;
+ }
+ transition: color 0.2s;
+`
export const BaseWrapper = styled.div`
${css.flex('align-center')};
`
diff --git a/src/containers/viewer/ArticleViewer/styles/post_viewer/fixed_header.ts b/src/containers/viewer/ArticleViewer/styles/post_viewer/fixed_header.ts
index f56acc07d..0fcdc58af 100644
--- a/src/containers/viewer/ArticleViewer/styles/post_viewer/fixed_header.ts
+++ b/src/containers/viewer/ArticleViewer/styles/post_viewer/fixed_header.ts
@@ -21,5 +21,5 @@ export const ArticleWrapper = styled.div`
export const ArticleTitle = styled.div`
font-size: 18px;
color: ${theme('thread.articleTitle')};
- ${css.cutRest('500px')};
+ ${css.cutRest('400px')};
`
diff --git a/src/containers/viewer/ArticleViewer/styles/post_viewer/index.tsx b/src/containers/viewer/ArticleViewer/styles/post_viewer/index.tsx
index e33fa18e3..72b78f56c 100644
--- a/src/containers/viewer/ArticleViewer/styles/post_viewer/index.tsx
+++ b/src/containers/viewer/ArticleViewer/styles/post_viewer/index.tsx
@@ -23,6 +23,3 @@ export const ArticleBody = styled.article`
line-height: 2em;
flex-grow: 1;
`
-export const Footer = styled.div`
- ${css.flex('align-both')};
-`
diff --git a/src/containers/viewer/ArticleViewer/styles/works_viewer/index.tsx b/src/containers/viewer/ArticleViewer/styles/works_viewer/index.ts
similarity index 78%
rename from src/containers/viewer/ArticleViewer/styles/works_viewer/index.tsx
rename to src/containers/viewer/ArticleViewer/styles/works_viewer/index.ts
index 8dbc24bef..24f44aae4 100644
--- a/src/containers/viewer/ArticleViewer/styles/works_viewer/index.tsx
+++ b/src/containers/viewer/ArticleViewer/styles/works_viewer/index.ts
@@ -1,6 +1,6 @@
import styled from 'styled-components'
-import { css, theme } from '@/utils'
+import { css } from '@/utils'
export const Wrapper = styled.div`
padding: 0 8px;
@@ -19,6 +19,3 @@ export const ArticleBody = styled.article`
line-height: 2em;
flex-grow: 1;
`
-export const Footer = styled.div`
- ${css.flex('align-both')};
-`
diff --git a/src/spec/account.ts b/src/spec/account.ts
index 2cf5fc4ab..415c213c7 100644
--- a/src/spec/account.ts
+++ b/src/spec/account.ts
@@ -1,15 +1,32 @@
import type { TPagedCommunities } from './community'
import type { TC11NLayout } from './c11n'
+type TSocial = {
+ qq?: string
+ weibo?: string
+ weichat?: string
+ github?: string
+ zhihu?: string
+ douban?: string
+ twitter?: string
+ facebook?: string
+ dribble?: string
+ instagram?: string
+ pinterest?: string
+ huaban?: string
+}
+
export type TUser = {
id?: string
login?: string
nickname?: string
name?: string
+ bio?: string
avatar?: string
// TODO: figure it out
extraId?: string
editableCommunities?: TPagedCommunities
+ social?: TSocial
}
export type TC11N = {
diff --git a/src/spec/article.ts b/src/spec/article.ts
index 9596a5faa..40f679a9c 100644
--- a/src/spec/article.ts
+++ b/src/spec/article.ts
@@ -1,19 +1,16 @@
import type { TCommunity, TTag } from './index'
-import type { TUser } from './account'
+import type { TUser, TAccount } from './account'
import type { TID } from './utils'
+export type TCopyright = 'cc' | 'approve' | 'forbid'
+
type TBaseArticle = {
id?: TID
title?: string
body?: string
views?: number
pin?: boolean
- author?: {
- id: string
- login: string
- nickname: string
- avatar: string
- }
+ author?: TAccount
starredCount?: number
origialCommunity?: TCommunity
commentsParticipators?: TUser
diff --git a/src/spec/index.ts b/src/spec/index.ts
index ed7848164..adcb14d89 100644
--- a/src/spec/index.ts
+++ b/src/spec/index.ts
@@ -55,6 +55,7 @@ export type {
TComment,
TPagedComments,
TArticleFilter,
+ TCopyright,
} from './article'
export type {
diff --git a/utils/themes/skins/solarized_dark.ts b/utils/themes/skins/solarized_dark.ts
index 0d3d1a253..04fb8bb98 100755
--- a/utils/themes/skins/solarized_dark.ts
+++ b/utils/themes/skins/solarized_dark.ts
@@ -263,8 +263,8 @@ const solarizedDark = {
hoverBg: lighten(0.05, bannerBg),
},
popover: {
- bg: '#0a3442',
- borderColor: darken(0.15, primaryColor),
+ bg: '#00333F',
+ borderColor: '#114e61',
boxShadow: '0px 7px 20px 10px rgba(0, 0, 0, 0.15)',
},
tags: {