Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@sentry/node": "5.17.0",
"@sentry/webpack-plugin": "1.11.1",
"@soywod/pin-field": "^0.1.9",
"@tippyjs/react": "4.2.0",
"@tippyjs/react": "4.2.5",
"@zeit/next-source-maps": "0.0.4-canary.1",
"accepts": "^1.3.4",
"apollo-cache-inmemory": "1.6.3",
Expand Down
Binary file added public/icons/static/emotion/beer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/biceps.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/confused.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/downvote.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/heart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/pao.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/pill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/popcorn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/static/emotion/tada.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { FC, memo } from 'react'

import type { TSIZE_SML } from '@/spec'
import { SIZE } from '@/constant'

import { AnimateOnChange } from 'react-animation'
import { Wrapper } from '../styles/total_count'

type TProps = {
count?: number
size?: TSIZE_SML
}
import type { TProps } from './index'
import { Wrapper } from './styles'

const AnimatedCount: FC<TProps> = ({ count = 0, size = SIZE.SMALL }) => {
const AnimatedCount: FC<TProps> = ({
count = 0,
size = SIZE.SMALL,
active = false,
}) => {
return (
<Wrapper size={size}>
<Wrapper size={size} $active={active}>
<AnimateOnChange
animationIn="fadeInUp"
animationOut="bounceOut"
Expand Down
62 changes: 62 additions & 0 deletions src/components/AnimatedCount/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { FC, memo, createContext, useContext } from 'react'
import dynamic from 'next/dynamic'

import type { TSIZE } from '@/spec'
import { SIZE } from '@/constant'
import { Wrapper } from './styles'

// @ts-ignore
const LoadingValueContext = createContext()

// props is not accessable in loading
// see https://github.com/vercel/next.js/issues/7906#issuecomment-787686440
const AnimatedCount = dynamic(() => import('./AnimatedCount'), {
/* eslint-disable react/display-name */
loading: () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const { count, size, active } = useContext(LoadingValueContext) as {
count: number
size: TSIZE
active: boolean
}
return (
<Wrapper size={size} $active={active}>
{count}
</Wrapper>
)
},
ssr: false,
})

export type TProps = {
count?: number
size?: TSIZE
active?: boolean
}

const Count: FC<TProps> = ({
count = 0,
size = SIZE.SMALL,
active = false,
}) => {
return (
<LoadingValueContext.Provider value={{ count, size, active }}>
<AnimatedCount count={count} size={size} active={active} />
</LoadingValueContext.Provider>
)
}

// debug
// const Count: FC<TProps> = ({ size = SIZE.SMALL }) => {
// const [count, setCount] = useState(0)

// return (
// <LoadingValueContext.Provider value={{ count, size }}>
// <div onClick={() => setCount(count + 1)}>
// <AnimatedCount count={count} size={size} />
// </div>
// </LoadingValueContext.Provider>
// )
// }

export default memo(Count)
17 changes: 17 additions & 0 deletions src/components/AnimatedCount/styles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from 'styled-components'

import type { TSIZE, TActive } from '@/spec'
import { theme } from '@/utils'

import { getFontSize } from './metric'

type TWrapper = { size: TSIZE } & TActive

export const Wrapper = styled.div<TWrapper>`
color: ${({ $active }) =>
$active ? '#139C9E' : theme('thread.articleTitle')};
font-size: ${({ size }) => getFontSize(size)};
font-weight: ${({ $active }) => ($active ? 'bold' : 'normal')};
overflow-y: hidden;
`
export const holder = 1
18 changes: 18 additions & 0 deletions src/components/AnimatedCount/styles/metric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { TSIZE } from '@/spec'
import { SIZE } from '@/constant'

export const getFontSize = (size: TSIZE): string => {
switch (size) {
case SIZE.TINY: {
return '13px'
}
case SIZE.LARGE: {
return '23px'
}
default: {
return '15px'
}
}
}

export const holder = 1
10 changes: 10 additions & 0 deletions src/components/AnimatedCount/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// import React from 'react'
// import { shallow } from 'enzyme'

// import AnimatedCount from '../index'

describe('TODO <AnimatedCount />', () => {
it('Expect to have unit tests specified', () => {
expect(true).toEqual(true)
})
})
23 changes: 23 additions & 0 deletions src/components/EmotionSelector/Panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { FC, memo } from 'react'

import { ICON } from '@/config'
import { Wrapper, EIcon } from './styles/panel'

const emotions = ['downvote', 'heart', 'confused', 'beer', 'popcorn', 'pill']

const EmojiPanel: FC = () => {
return (
<Wrapper>
{emotions.map((item) => (
<EIcon
key={item}
src={`${ICON}/emotion/${item}.png`}
name={item}
noLazy
/>
))}
</Wrapper>
)
}

export default memo(EmojiPanel)
69 changes: 69 additions & 0 deletions src/components/EmotionSelector/SelectedEmotions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* EmojiSelector
*/

import { FC, memo, Fragment } from 'react'
import { buildLog } from '@/utils'
import { keys } from 'ramda'

import { ICON } from '@/config'
import Tooltip from '@/components/Tooltip'
import AnimatedCount from '@/components/AnimatedCount'

import {
Wrapper,
EIcon,
PopHint,
PopUsers,
Count,
} from './styles/selected_emotions'

/* eslint-disable-next-line */
const log = buildLog('c:SelectedEmotions:index')

const getEmotionName = (item): string => {
const eCountKey = keys(item)[0] as string
return eCountKey.split('Count')[0]
}

const Emotion: FC<{ name: string; count: number }> = ({ name, count }) => {
const emotionIcon = (
<EIcon src={`${ICON}/emotion/${name}.png`} name={name} noLazy />
)
return (
<Tooltip
content={
<PopHint>
<PopUsers>xxx, yyy, zzz 等 7 人</PopUsers> {emotionIcon}
</PopHint>
}
noPadding
>
<Wrapper>
{emotionIcon}
<Count>
<AnimatedCount count={count} size="tiny" active={false} />
</Count>
</Wrapper>
</Tooltip>
)
}

type TProps = {
emotions: Record<string, number | string[] | boolean>[]
}

const SelectedEmotions: FC<TProps> = ({ emotions }) => {
return (
<Fragment>
{emotions.map((item) => {
const eName = getEmotionName(item) as string
const count = item[`${eName}Count`] as number

return <Emotion key={eName} name={eName} count={count} />
})}
</Fragment>
)
}

export default memo(SelectedEmotions)
54 changes: 54 additions & 0 deletions src/components/EmotionSelector/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* EmojiSelector
*/

import { FC, memo } from 'react'
import { buildLog } from '@/utils'

import { IconButton } from '@/components/Buttons'
import Tooltip from '@/components/Tooltip'

import SelectedEmotions from './SelectedEmotions'
import Panel from './Panel'
import { Wrapper } from './styles'

/* eslint-disable-next-line */
const log = buildLog('c:EmotionSelector:index')

const tmpEmotions = [
{
downvoteCount: 5,
},
{
heartCount: 10,
},
{
confusedCount: 7,
},
{
beerCount: 3,
},
{
popcornCount: 12,
},
{
pillCount: 20,
},
]

type TProps = {
testid?: string
}

const EmotionSelector: FC<TProps> = ({ testid = 'emotion-selector' }) => {
return (
<Wrapper testid={testid}>
<SelectedEmotions emotions={tmpEmotions} />
<Tooltip content={<Panel />} trigger="click">
<IconButton path="emotion/emotion.svg" mRight={0} mTop={1} />
</Tooltip>
</Wrapper>
)
}

export default memo(EmotionSelector)
17 changes: 17 additions & 0 deletions src/components/EmotionSelector/styles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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.flex('align-center')};
/* background: #043642; */
padding: 3px 6px;
padding-right: 0;
border-radius: 8px;
margin-left: -4px;
`
export const holder = 1
25 changes: 25 additions & 0 deletions src/components/EmotionSelector/styles/panel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from 'styled-components'

import Img from '@/Img'
import { css } from '@/utils'

export const Wrapper = styled.div`
${css.flex('align-center', 'justify-center')};
width: 200px;
`
export const EIcon = styled(Img)<{ name: string }>`
margin-top: ${({ name }) => (name === 'downvote' ? '2px' : 0)};
${({ name }) =>
name === 'confused' || name === 'popcorn' ? css.size(21) : css.size(20)};
margin-right: ${({ name }) => (name === 'pill' ? 0 : '15px')};

filter: saturate(0.6);
opacity: 0.9;
z-index: 1;

&:hover {
cursor: pointer;
filter: saturate(1);
opacity: 1;
}
`
44 changes: 44 additions & 0 deletions src/components/EmotionSelector/styles/selected_emotions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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;
margin-right: 14px;
margin-right: 5px;
padding: 0 5px;
border-radius: 5px;
margin-left: -5px;

&:hover {
background: #023c4a;
}
`
export const EIcon = styled(Img)<{ name: string }>`
margin-top: ${({ name }) => (name === 'downvote' ? '2px' : 0)};
${({ name }) =>
name === 'confused' || name === 'popcorn' ? css.size(15) : css.size(14)};
margin-right: 6px;

filter: saturate(0.6);
opacity: 0.9;
`
export const Count = styled.div`
opacity: 0.8;

${Wrapper}:hover & {
color: #00a59b;
}
`
export const PopUsers = styled.div`
color: ${theme('thread.articleTitle')};
font-size: 13px;
margin-right: 5px;
`
export const PopHint = styled.div`
${css.flex('align-center')};
padding: 3px 5px;
padding-left: 10px;
`
10 changes: 10 additions & 0 deletions src/components/EmotionSelector/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// import React from 'react'
// import { shallow } from 'enzyme'

// import EmojiSelector from '../index'

describe('TODO <EmojiSelector />', () => {
it('Expect to have unit tests specified', () => {
expect(true).toEqual(true)
})
})
Loading