diff --git a/package-lock.json b/package-lock.json index b1de9c2bd..79098c608 100755 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,8 @@ "next-compose-plugins": "^2.2.0", "next-i18next": "4.4.1", "next-pwa": "^5.6.0", - "overlayscrollbars": "^2.1.0", + "overlayscrollbars": "^2.4.5", + "overlayscrollbars-react": "^0.5.3", "promise-timeout": "^1.3.0", "prop-types": "^15.5.10", "qrcode.react": "^3.1.0", @@ -17427,9 +17428,18 @@ "dev": true }, "node_modules/overlayscrollbars": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.4.4.tgz", - "integrity": "sha512-792lwASLr3FlZER+/P7NseFQjffDEcQOg6HtyBSLrnb3crH+Ybk0tzaljQVQZs0pjGF/xFjyvMKin6whkL0RnQ==" + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.4.5.tgz", + "integrity": "sha512-4OLCPuZPVdd1HnDLYS4o+kAsOCZwVz6dDA212m8ki/u3isltKyWGVjIv2aqpVHkDRf/P2K98m9Su8pdhihtAIQ==" + }, + "node_modules/overlayscrollbars-react": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/overlayscrollbars-react/-/overlayscrollbars-react-0.5.3.tgz", + "integrity": "sha512-mq9D9tbfSeq0cti1kKMf3B3AzsEGwHcRIDX/K49CvYkHz/tKeU38GiahDkIPKTMEAp6lzKCo4x1eJZA6ZFYOxQ==", + "peerDependencies": { + "overlayscrollbars": "^2.0.0", + "react": ">=16.8.0" + } }, "node_modules/p-each-series": { "version": "2.2.0", diff --git a/package.json b/package.json index 017f04d0a..adf4500dc 100755 --- a/package.json +++ b/package.json @@ -64,7 +64,8 @@ "next-compose-plugins": "^2.2.0", "next-i18next": "4.4.1", "next-pwa": "^5.6.0", - "overlayscrollbars": "^2.1.0", + "overlayscrollbars": "^2.4.5", + "overlayscrollbars-react": "^0.5.3", "promise-timeout": "^1.3.0", "prop-types": "^15.5.10", "qrcode.react": "^3.1.0", diff --git a/src/containers/Mushroom/logic.ts b/src/containers/Mushroom/logic.ts index edef935a1..64f3bd150 100644 --- a/src/containers/Mushroom/logic.ts +++ b/src/containers/Mushroom/logic.ts @@ -34,7 +34,12 @@ let sub$ = null const { SR71, $solver, asyncRes, asyncErr } = asyncSuit const sr71$ = new SR71({ // @ts-ignore - receive: [EVENT.UPVOTE_ARTICLE, EVENT.UPDATE_VIEWING_ARTICLE, EVENT.REFRESH_ARTICLES], + receive: [ + EVENT.UPVOTE_ARTICLE, + EVENT.UPDATE_VIEWING_ARTICLE, + EVENT.REFRESH_ARTICLES, + EVENT.LIST_USER_MODAL, + ], }) // custromScroll's scroll direction change @@ -168,6 +173,13 @@ const DataSolver = [ store.syncArticle(article) }, }, + { + match: asyncRes(EVENT.LIST_USER_MODAL), + action: () => { + store.mark({ showUserListModal: true }) + }, + }, + { match: asyncRes(EVENT.UPVOTE_ARTICLE), action: (_data) => { diff --git a/src/containers/Mushroom/store.ts b/src/containers/Mushroom/store.ts index 1daf2040f..6459083c1 100644 --- a/src/containers/Mushroom/store.ts +++ b/src/containers/Mushroom/store.ts @@ -22,6 +22,8 @@ import { T, getParent, markStates, Instance, toJS, useMobxContext } from '@/mobx const MushroomStore = T.model('MushroomStore', { online: T.opt(T.bool, true), isMobile: T.opt(T.bool, false), + + showUserListModal: T.opt(T.bool, false), // follow the mac convention bodyScrollDirection: T.opt(T.enum(['up', 'down']), 'up'), // activeState; @@ -110,6 +112,9 @@ const MushroomStore = T.model('MushroomStore', { const root = getParent(self) as TRootStore return root.dashboardThread.clearLocalSettings() }, + closeUserListModal(): void { + self.showUserListModal = false + }, authWarning(options): void { const root = getParent(self) as TRootStore root.authWarning(options) diff --git a/src/containers/dynamic/index.tsx b/src/containers/dynamic/index.tsx index efcb2d548..df745d509 100755 --- a/src/containers/dynamic/index.tsx +++ b/src/containers/dynamic/index.tsx @@ -7,6 +7,4 @@ export const Comments = dynamic(() => import('../unit/Comments'), { ssr: false, }) -export const Cashier = dynamic(() => import('../tool/Cashier'), { - ssr: false, -}) +export const holder = 1 diff --git a/src/containers/editor/TagSettingEditor/index.tsx b/src/containers/editor/TagSettingEditor/index.tsx index 8d176ab58..a792e8d6a 100644 --- a/src/containers/editor/TagSettingEditor/index.tsx +++ b/src/containers/editor/TagSettingEditor/index.tsx @@ -42,18 +42,17 @@ import { observer } from 'mobx-react-lite' // const log = buildLog('C:TagSettingEditor') type TProps = { - testid: string mode?: TChangeMode } -const TagSettingEditor: FC = ({ testid, mode = CHANGE_MODE.UPDATE }) => { +const TagSettingEditor: FC = ({ mode = CHANGE_MODE.UPDATE }) => { const store = useStore() useInit(store, mode) const { editingTagData: editingTag, curCategory, categoryOptions, processing } = store return ( - + { - + {tab === TAB.BUILDIN && } {tab === TAB.UPLOAD && } diff --git a/src/containers/thread/DashboardThread/SideMenu/index.tsx b/src/containers/thread/DashboardThread/SideMenu/index.tsx index ba7865d4c..364804c6c 100755 --- a/src/containers/thread/DashboardThread/SideMenu/index.tsx +++ b/src/containers/thread/DashboardThread/SideMenu/index.tsx @@ -1,7 +1,7 @@ import { FC, memo } from 'react' import { keys } from 'ramda' -import type { TCommunity, TDashboardPath } from '@/spec' +import type { TDashboardPath } from '@/spec' import Sticky from '@/widgets/Sticky' import { MENU } from '../constant' diff --git a/src/containers/thread/DashboardThread/styles/side_menu/group.ts b/src/containers/thread/DashboardThread/styles/side_menu/group.ts index 200375cf2..8e973ecdc 100755 --- a/src/containers/thread/DashboardThread/styles/side_menu/group.ts +++ b/src/containers/thread/DashboardThread/styles/side_menu/group.ts @@ -66,7 +66,7 @@ export const Item = styled(Link)` display: block; color: ${({ $active, $color }) => $active ? rainbow($color, 'dashboard.menuTitle') : theme('dashboard.menuTitle')}; - background: ${({ $active }) => ($active ? theme('activeLinear') : 'transparent')}; + background: ${({ $active }) => ($active ? theme('hoverBg') : 'transparent')}; font-weight: ${({ $active }) => ($active ? 500 : 400)}; width: 160px; @@ -81,7 +81,7 @@ export const Item = styled(Link)` &:hover { cursor: pointer; color: ${({ $color }) => rainbow($color, 'dashboard.menuTitle')}; - background: ${theme('activeLinear')}; + background: ${theme('hoverBg')}; } &:before { diff --git a/src/containers/thread/PostThread/ThreadSidebar/index.tsx b/src/containers/thread/PostThread/ThreadSidebar/index.tsx index dfc86332a..5c1f69c64 100644 --- a/src/containers/thread/PostThread/ThreadSidebar/index.tsx +++ b/src/containers/thread/PostThread/ThreadSidebar/index.tsx @@ -15,7 +15,7 @@ import useViewingCommunity from '@/hooks/useViewingCommunity' import useActiveTag from '@/hooks/useActiveTag' import { buildLog } from '@/logger' -import { refreshArticles, callGEditor, callSyncSelector } from '@/signal' +import { refreshArticles, callGEditor, callSyncSelector, listUsers } from '@/signal' import { toJS } from '@/mobx' import { mockUsers } from '@/mock' @@ -77,7 +77,7 @@ const ThreadSidebar: FC = () => { fallback={} /> ))} - +2 + listUsers('drawer')}>+2 diff --git a/src/containers/thread/PostThread/index.tsx b/src/containers/thread/PostThread/index.tsx index 590503f3a..e7a051449 100644 --- a/src/containers/thread/PostThread/index.tsx +++ b/src/containers/thread/PostThread/index.tsx @@ -4,7 +4,7 @@ * */ -import { FC, useEffect, useRef } from 'react' +import { FC, useRef } from 'react' import { observer } from 'mobx-react-lite' import type { TResState } from '@/spec' @@ -18,28 +18,16 @@ import { THREAD } from '@/constant/thread' import PagedPosts from '@/widgets/PagedPosts' import TagNote from '@/widgets/TagNote' -import ViewportTracker from '@/widgets/ViewportTracker' import ArticlesFilter from '@/widgets/ArticlesFilter' // import LavaLampLoading from '@/widgets/Loading/LavaLampLoading' import ThreadSidebar from './ThreadSidebar' import { Wrapper, MainWrapper, SidebarWrapper, FilterWrapper } from './styles' -import { inAnchor, outAnchor, onFilterSelect } from './logic' /* eslint-disable-next-line */ const log = buildLog('C:PostThread') -const isInViewport = (element) => { - const rect = element.getBoundingClientRect() - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && - rect.right <= (window.innerWidth || document.documentElement.clientWidth) - ) -} - const PostThread: FC = () => { const bannerLayout = useBannerLayout() const { resState } = usePagedPosts() @@ -47,12 +35,6 @@ const PostThread: FC = () => { const postLayout = usePostLayout() const trackerRef = useRef(null) - useEffect(() => { - if (trackerRef.current) { - isInViewport(trackerRef.current) ? inAnchor() : outAnchor() - } - }, [trackerRef]) - // if (store.curThread !== THREAD.POST) return const isMobile = false @@ -64,8 +46,6 @@ const PostThread: FC = () => { return ( - - {showFilters && ( diff --git a/src/containers/thread/PostThread/logic.ts b/src/containers/thread/PostThread/logic.ts deleted file mode 100644 index cb036b56d..000000000 --- a/src/containers/thread/PostThread/logic.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { TArticleFilter } from '@/spec' - -import { scrollToHeader } from '@/dom' -import { buildLog } from '@/logger' - -// import S from './schema' - -/* eslint-disable-next-line */ -const log = buildLog('L:ArticlesThread') - -export const inAnchor = (): void => { - // console.log('## inAnchor') -} -export const outAnchor = (): void => { - // console.log('## outAnchor') -} - -export const onFilterSelect = (option: TArticleFilter): void => { - // store.selectFilter(option) - // console.log('cur filter: ', store.filtersData) - loadArticles() -} - -/** - * load paged articles then save them to store - */ -const loadArticles = (page = 1): void => { - console.log('## do loadArticles') - scrollToHeader() -} - -// do query paged articles -const doQuery = (page: number): void => { - // const args = store.getLoadArgs(page) - // log('args: ', args) - // sr71$.query(S.getPagedArticlesSchema(store.curThread), args) -} diff --git a/src/containers/thread/PostThread/styles/thread_sidebar/community_brief.ts b/src/containers/thread/PostThread/styles/thread_sidebar/community_brief.ts index 7c9f13466..11b8f88b8 100644 --- a/src/containers/thread/PostThread/styles/thread_sidebar/community_brief.ts +++ b/src/containers/thread/PostThread/styles/thread_sidebar/community_brief.ts @@ -13,20 +13,20 @@ export const Wrapper = styled.div` ` export const Brief = styled.div` margin-bottom: 10px; - margin-left: 14px; + margin-left: 12px; ` export const Logo = styled(Img)` - ${css.size(40)}; - margin-top: -5px; + ${css.size(32)}; + margin-top: -6px; ` export const Title = styled.div` - font-size: 16px; + font-size: 15px; font-weight: 600; color: ${theme('article.title')}; ` export const InfoBar = styled.div` ${css.row('align-center')}; - margin-top: 2px; + margin-top: 1px; ` export const Label = styled.div` font-size: 13px; diff --git a/src/containers/thread/PostThread/styles/thread_sidebar/index.ts b/src/containers/thread/PostThread/styles/thread_sidebar/index.ts index 69e995284..cbab5fa4e 100644 --- a/src/containers/thread/PostThread/styles/thread_sidebar/index.ts +++ b/src/containers/thread/PostThread/styles/thread_sidebar/index.ts @@ -36,12 +36,13 @@ export const MoreNum = styled.div` color: ${theme('article.digest')}; font-size: 15px; margin-top: 1px; - margin-left: 2px; + margin-left: 4px; letter-spacing: 1px; opacity: 0.8; &:hover { color: ${theme('article.title')}; + background: ${theme('hoverBg')}; opacity: 1; cursor: pointer; } diff --git a/src/containers/tool/Cashier/Content.tsx b/src/containers/tool/Cashier/Content.tsx deleted file mode 100755 index 778660f2a..000000000 --- a/src/containers/tool/Cashier/Content.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { FC, memo } from 'react' - -// import { ICON_CMD } from '@/config' -import PaymentContent from './PaymentContent' -import QuestionContent from './QuestionContent' - -import type { TContentView, TAmount, TSubContentView } from './spec' -import { Wrapper } from './styles/content' - -export type TProps = { - contentView: TContentView - subContentView: TSubContentView - amount: TAmount - paymentMethod: string // todo - transferAccount: string // TODO -} - -const Componet: FC = ({ - contentView, - amount, - paymentMethod, - subContentView, - transferAccount, -}) => { - switch (contentView) { - case 'question': - return - - default: - return ( - - - - ) - } -} - -export default memo(Componet) diff --git a/src/containers/tool/Cashier/PaymentConfirm.tsx b/src/containers/tool/Cashier/PaymentConfirm.tsx deleted file mode 100755 index 64585db85..000000000 --- a/src/containers/tool/Cashier/PaymentConfirm.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { FC, memo } from 'react' - -import Button from '@/widgets/Buttons/Button' -import FormItem from '@/widgets/FormItem' - -import type { TProps as TContentProps } from './Content' -import { Wrapper, Desc, BtnWrapper } from './styles/payment_confirm' -import { transferAccountChange, onPaymentConfirm } from './logic' - -const trans = { - WECHAT: '微信支付', - ALIPAY: '支付宝', -} - -type TProps = Pick - -const PaymentConfirm: FC = ({ paymentMethod, transferAccount }) => { - return ( - - - - 感谢打赏!最后请正确填写您的 - {trans[paymentMethod]} - 账户名以便核实,我们将在 0~24 小时内为您办理相关服务。 - - - - - - ) -} - -export default memo(PaymentConfirm) diff --git a/src/containers/tool/Cashier/PaymentContent.tsx b/src/containers/tool/Cashier/PaymentContent.tsx deleted file mode 100755 index 4bfd13720..000000000 --- a/src/containers/tool/Cashier/PaymentContent.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { FC, memo } from 'react' - -import { ICON_BASE } from '@/config' - -// import { ICON_CMD } from '@/config' -import PaymentConfirm from './PaymentConfirm' - -import type { TProps as TContentProps } from './Content' -import { - Wrapper, - CountDesc, - DescNumber, - PaymentPic, - NextDesc, - NextStepBtn, -} from './styles/payment_content' - -import { subContentViewOnChange } from './logic' - -const QR_CODE_ADDR = { - ALIPAY: { - 10.24: `${ICON_BASE}/payment/alipay-10.24.png`, - 51.2: `${ICON_BASE}/payment/alipay-51.2.png`, - 102.4: `${ICON_BASE}/payment/alipay-102.4.png`, - 512: `${ICON_BASE}/payment/alipay-512.png`, - 1024: `${ICON_BASE}/payment/alipay-1024.png`, - }, - WECHAT: { - 10.24: `${ICON_BASE}/payment/wechat-10.24.png`, - 51.2: `${ICON_BASE}/payment/wechat-51.2.png`, - 102.4: `${ICON_BASE}/payment/wechat-102.4.png`, - 512: `${ICON_BASE}/payment/wechat-512.png`, - 1024: `${ICON_BASE}/payment/wechat-1024.png`, - }, -} - -type TProps = Pick< - TContentProps, - 'amount' | 'transferAccount' | 'paymentMethod' | 'subContentView' -> - -const PaymentContent: FC = ({ - amount, - paymentMethod, - subContentView, - transferAccount, -}) => { - switch (subContentView) { - case 'confirm': - return ( - - ) - - default: - return ( - - - 资助 {amount} 元 - - - - 付款完成后,请进入 - subContentViewOnChange('confirm')}> - 下一步 - - - - ) - } -} - -export default memo(PaymentContent) diff --git a/src/containers/tool/Cashier/PaymentSidebar.tsx b/src/containers/tool/Cashier/PaymentSidebar.tsx deleted file mode 100755 index 566b9a544..000000000 --- a/src/containers/tool/Cashier/PaymentSidebar.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { FC, memo } from 'react' - -import { ICON_CMD } from '@/config' -import { PAYMENT_METHOD } from '@/constant/payment' -import useAccount from '@/hooks/useAccount' - -import type { TProps as TContentProps } from './Content' -import { - Wrapper, - TransWrapper, - AccountIcon, - TransIcon, - SiteLogo, - SelectorWrapper, - SelectorTitle, - TitleDivider, - WeixinWrapper, - AliWrapper, - Holder, - QuestionWrapper, - OptionTitle, - FaceValueWrapper, - FaceValueNum, - PaymentIcon, - QuestionIcon, -} from './styles/payment_sidebar' - -import { sidebarViewOnChange, paymentMethodOnChange } from './logic' - -type TProps = Pick - -const PaymentSidebar: FC = ({ paymentMethod, amount, subContentView }) => { - const accountInfo = useAccount() - - if (!accountInfo) return null - - return ( - - - - - - - - {subContentView === 'confirm' ? ( - - 付款方式 - - - - 支付宝 - - - - 微信支付 - 微信支付 - - - 付款金额 - - - {amount} 元 - - - - ) : ( - - 付款方式 - - paymentMethodOnChange(PAYMENT_METHOD.ALIPAY)} - > - - 支付宝 - - paymentMethodOnChange(PAYMENT_METHOD.WECHAT)} - > - - 微信支付 - - - sidebarViewOnChange('question')}> - - 常见问题 - - - )} - - ) -} - -export default memo(PaymentSidebar) diff --git a/src/containers/tool/Cashier/QuestionContent.tsx b/src/containers/tool/Cashier/QuestionContent.tsx deleted file mode 100755 index 7e4f187ad..000000000 --- a/src/containers/tool/Cashier/QuestionContent.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { FC, memo } from 'react' - -// import { ICON_CMD } from '@/config' -import { Wrapper, Title, Desc, Divider } from './styles/question_content' - -const QuestionContent: FC = () => { - return ( - - 为什么要手动填写付款信息 ? - - 国内支付平台都需要企业认证。 - 目前公司虽已注册,但因为名称等问题且需要一定时间对接调试,在此之前只支持手动充值, - 请谅解。 - - - 付款成功但是 未填写/填错 账户信息怎么办 ? - - 这种情况您可以将相关账户信息发送邮件至 member@group.groupher.com, - 客服会尽快为您处理。 - - - 资金的主要用途是什么?(软件还要钱 ??) - - groupher 目前的团队规模是非全职的个位数, - 无法仅靠情怀支撑巨大的时间/物质成本, - 您的资助将主要用于网站的开发/维护/运营等, 使平台变得更稳定, - 更好的服务像你我一样的广大 IT 从业者。 - - - 还有什么福利吗 ? - - 除了会员的各种服务以外,捐助 500 - 元以上者可以在感谢页面留下您的足迹,详情查看。 - - - ) -} - -export default memo(QuestionContent) diff --git a/src/containers/tool/Cashier/QuestionSidebar.tsx b/src/containers/tool/Cashier/QuestionSidebar.tsx deleted file mode 100755 index 0d1c62b4a..000000000 --- a/src/containers/tool/Cashier/QuestionSidebar.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { FC, memo } from 'react' - -import { ICON_CMD } from '@/config' - -import { - Wrapper, - BackBtnWrapper, - BackIcon, - BackTitle, - Holder, -} from './styles/question_sidebar' - -import { sidebarViewOnChange } from './logic' - -const QuestionSidebar: FC = () => { - return ( - - sidebarViewOnChange('pay')}> - - 返回付款 - - - - ) -} - -export default memo(QuestionSidebar) diff --git a/src/containers/tool/Cashier/Sidebar.tsx b/src/containers/tool/Cashier/Sidebar.tsx deleted file mode 100755 index a0af392ca..000000000 --- a/src/containers/tool/Cashier/Sidebar.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { FC, memo } from 'react' - -import PaymentSidebar from './PaymentSidebar' -import QuestionSidebar from './QuestionSidebar' - -import type { TProps as TContentProps } from './Content' -import type { TContentView } from './spec' -import { Wrapper } from './styles/sidebar' - -type TProps = Pick< - TContentProps, - 'amount' | 'paymentMethod' | 'subContentView' -> & { sidebarView: TContentView } - -const Sidebar: FC = ({ - sidebarView, - amount, - paymentMethod, - subContentView, -}) => { - switch (sidebarView) { - case 'question': - return ( - - - - ) - - default: - return ( - - - - ) - } -} - -export default memo(Sidebar) diff --git a/src/containers/tool/Cashier/constant.ts b/src/containers/tool/Cashier/constant.ts deleted file mode 100755 index 0dbf5ed30..000000000 --- a/src/containers/tool/Cashier/constant.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { TContentView, TSubContentView, TAmount } from './spec' - -export const SIDEBAR_VIEW = { - PAY: 'pay' as TContentView, - QUESTION: 'question' as TContentView, -} - -export const SUBCONTENT_VIEW = { - PAY: 'pay' as TSubContentView, - CONFIRM: 'question' as TSubContentView, -} - -export const AMOUNT = { - 10.24: '10.24' as TAmount, - 51.2: '51.2' as TAmount, - 102.4: '102.4' as TAmount, - 512: '512' as TAmount, - 1024: '1024' as TAmount, -} diff --git a/src/containers/tool/Cashier/index.tsx b/src/containers/tool/Cashier/index.tsx deleted file mode 100755 index 20bb65f45..000000000 --- a/src/containers/tool/Cashier/index.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Cashier - * - */ - -import { FC } from 'react' -import { observer } from 'mobx-react-lite' - -import { buildLog } from '@/logger' - -import Modal from '@/widgets/Modal' - -import Sidebar from './Sidebar' -import Content from './Content' - -import { useStore } from './store' -import { Wrapper } from './styles' -import { useInit, onClose } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:Cashier') - -const Cashier: FC = () => { - const store = useStore() - useInit(store) - - const { show, sidebarView, contentView, subContentView, paymentMethod, amount, transferAccount } = - store - - return ( - - - - - - - ) -} - -export default observer(Cashier) diff --git a/src/containers/tool/Cashier/logic.ts b/src/containers/tool/Cashier/logic.ts deleted file mode 100755 index 272091af7..000000000 --- a/src/containers/tool/Cashier/logic.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { useEffect } from 'react' -import { isEmpty } from 'ramda' - -import EVENT from '@/constant/event' -import ERR from '@/constant/err' - -import asyncSuit from '@/async' -import { errorForHuman } from '@/utils/errors' -import { Global } from '@/helper' -import { send, errRescue, toast } from '@/signal' -import { buildLog } from '@/logger' - -import type { TStore } from './store' -import S from './schema' - -const { SR71, $solver, asyncRes, asyncErr } = asyncSuit - -const sr71$ = new SR71({ - // @ts-ignore - receive: [EVENT.CALL_CASHIER], -}) - -let store: TStore | undefined -let sub$ = null - -/* eslint-disable-next-line */ -const log = buildLog('L:Cashier') - -export const sidebarViewOnChange = (sidebarView): void => - store.mark({ sidebarView, contentView: sidebarView }) - -export const paymentMethodOnChange = (paymentMethod): void => store.mark({ paymentMethod }) - -export const subContentViewOnChange = (subContentView): void => store.mark({ subContentView }) - -export const transferAccountChange = ({ target: { value } }) => - store.mark({ transferAccount: value }) - -export const onPaymentConfirm = (): void => { - if (!store.isLogin) return store.authWarning({ hideToast: true }) - if (isEmpty(store.transferAccount)) { - return toast('提交失败: 请填写转账信息', 'error') - } - - const { paymentMethod, paymentUsage, amount, transferAccount: note } = store - - const args = { - paymentMethod, - paymentUsage, - amount: parseFloat(amount), - note, - } - log('onPaymentConfirm: ', args) - sr71$.mutate(S.createBill, args) -} - -export const onClose = (): void => { - const confirmed = Global.confirm('若已付款,请确保您填写了账户信息') - - if (confirmed) return store.mark({ show: false, subContentView: 'pay' }) -} - -// ############################### -// Data & Error handlers -// ############################### - -const DataSolver = [ - { - match: asyncRes(EVENT.CALL_CASHIER), - action: (data) => { - const { amount, usage } = data[EVENT.CALL_CASHIER] - store.mark({ show: true, amount: String(amount), paymentUsage: usage }) - }, - }, - { - match: asyncRes('createBill'), - action: ({ createBill }) => { - log('createBill done: ', createBill) - store.mark({ show: false, subContentView: 'pay' }) - send(EVENT.NEW_BILLS) - }, - }, -] - -const ErrSolver = [ - { - match: asyncErr(ERR.GRAPHQL), - action: ({ details }) => toast(`提交失败: ${errorForHuman(details)}`, 'error'), - }, - { - match: asyncErr(ERR.TIMEOUT), - action: ({ details }) => errRescue({ type: ERR.TIMEOUT, details, path: 'Cashier' }), - }, - { - match: asyncErr(ERR.NETWORK), - action: () => errRescue({ type: ERR.NETWORK, path: 'Cashier' }), - }, -] - -// ############################### -// init & uninit -// ############################### -export const useInit = (_store: TStore): void => { - useEffect(() => { - store = _store - // log('effect init') - sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) - - return () => { - // log('effect uninit') - sr71$.stop() - sub$.unsubscribe() - } - }, [_store]) -} diff --git a/src/containers/tool/Cashier/schema.ts b/src/containers/tool/Cashier/schema.ts deleted file mode 100755 index a94f8f33e..000000000 --- a/src/containers/tool/Cashier/schema.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { gql } from 'urql/core' - -const createBill = gql` - mutation ( - $paymentMethod: PaymentMethodEnum! - $paymentUsage: PaymentUsageEnum! - $amount: Float! - $note: String - ) { - createBill( - paymentMethod: $paymentMethod - paymentUsage: $paymentUsage - amount: $amount - note: $note - ) { - id - state - amount - hashId - paymentUsage - paymentMethod - note - } - } -` -const pagedBillRecords = gql` - query ($filter: PagiFilter!) { - pagedBillRecords(filter: $filter) { - entries { - id - state - amount - hashId - paymentUsage - paymentMethod - note - } - totalPages - totalCount - pageSize - pageNumber - } - } -` -const schema = { - createBill, - pagedBillRecords, -} - -export default schema diff --git a/src/containers/tool/Cashier/spec.d.ts b/src/containers/tool/Cashier/spec.d.ts deleted file mode 100755 index 404d0ddf3..000000000 --- a/src/containers/tool/Cashier/spec.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type TContentView = 'pay' | 'question' -export type TSubContentView = 'pay' | 'confirm' -export type TAmount = '10.24' | '51.2' | '102.4' | '512' | '1024' diff --git a/src/containers/tool/Cashier/store.ts b/src/containers/tool/Cashier/store.ts deleted file mode 100755 index 70a49af6f..000000000 --- a/src/containers/tool/Cashier/store.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Cashier store - * - */ - -import { values } from 'ramda' - -import type { TRootStore, TAccount } from '@/spec' - -import { PAYMENT_USAGE, PAYMENT_METHOD } from '@/constant/payment' -import { T, markStates, Instance, getParent, useMobxContext } from '@/mobx' - -import { AMOUNT, SIDEBAR_VIEW, SUBCONTENT_VIEW } from './constant' - -const Cashier = T.model('Cashier', { - show: T.opt(T.bool, false), - transferAccount: T.opt(T.string, ''), - sidebarView: T.opt(T.enum('sideView', values(SIDEBAR_VIEW)), SIDEBAR_VIEW.PAY), - contentView: T.opt(T.enum('contentView', values(SIDEBAR_VIEW)), SIDEBAR_VIEW.PAY), - subContentView: T.opt(T.enum('subContentView', values(SUBCONTENT_VIEW)), SUBCONTENT_VIEW.PAY), - paymentMethod: T.opt(T.enum('paymentMethod', values(PAYMENT_METHOD)), PAYMENT_METHOD.ALIPAY), - paymentUsage: T.opt(T.enum('paymentUsage', values(PAYMENT_USAGE)), PAYMENT_USAGE.SENIOR), - amount: T.opt(T.enum('amount', values(AMOUNT)), AMOUNT['10.24']), -}) - .views((self) => ({ - get accountInfo(): TAccount { - const root = getParent(self) as TRootStore - return root.accountInfo - }, - get isLogin(): boolean { - const root = getParent(self) as TRootStore - return root.account.isLogin - }, - })) - .actions((self) => ({ - authWarning(options): void { - const root = getParent(self) as TRootStore - root.authWarning(options) - }, - callCashier({ paymentUsage, amount }): void { - self.show = true - self.paymentUsage = paymentUsage - // @ts-ignore - self.amount = String(amount) - }, - mark(sobj: Record): void { - markStates(sobj, self) - }, - })) - -export type TStore = Instance -export const useStore = (): TStore => useMobxContext().store.cashier - -export default Cashier diff --git a/src/containers/tool/Cashier/styles/content.ts b/src/containers/tool/Cashier/styles/content.ts deleted file mode 100755 index 9e549b224..000000000 --- a/src/containers/tool/Cashier/styles/content.ts +++ /dev/null @@ -1,10 +0,0 @@ -import styled from 'styled-components' - -// import Img from '@/Img' -import css from '@/css' - -export const Wrapper = styled.div` - ${css.columnGrow('align-center')}; -` - -export const holder = 1 diff --git a/src/containers/tool/Cashier/styles/index.ts b/src/containers/tool/Cashier/styles/index.ts deleted file mode 100755 index 300d484f5..000000000 --- a/src/containers/tool/Cashier/styles/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import styled from 'styled-components' - -// import Img from '@/Img' -// import css from '@/css' - -export const Wrapper = styled.div` - display: flex; - padding: 20px; -` - -export const holder = 1 diff --git a/src/containers/tool/Cashier/styles/payment_confirm.ts b/src/containers/tool/Cashier/styles/payment_confirm.ts deleted file mode 100755 index 9fb9b90e4..000000000 --- a/src/containers/tool/Cashier/styles/payment_confirm.ts +++ /dev/null @@ -1,19 +0,0 @@ -import styled from 'styled-components' - -// import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - ${css.columnGrow('align-center')}; - margin-top: 30px; - width: 80%; -` -export const Desc = styled.div` - ${css.row('align-center')}; - margin-top: 10px; - color: ${theme('article.digest')}; -` -export const BtnWrapper = styled.div` - align-self: flex-end; - margin-top: 120px; -` diff --git a/src/containers/tool/Cashier/styles/payment_content.ts b/src/containers/tool/Cashier/styles/payment_content.ts deleted file mode 100755 index 426b2d821..000000000 --- a/src/containers/tool/Cashier/styles/payment_content.ts +++ /dev/null @@ -1,41 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - ${css.columnGrow('align-center')}; - margin-top: 10px; -` -export const CountDesc = styled.div` - color: ${theme('article.digest')}; - margin-bottom: 10px; -` -export const DescNumber = styled.span` - color: #139c9e; - font-weight: bold; -` -export const NextDesc = styled.div` - margin-top: 15px; - color: ${theme('article.digest')}; -` -export const NextStepBtn = styled.span` - border: 1px solid; - border-color: ${theme('article.title')}; - padding: 0 3px; - border-radius: 4px; - margin-left: 6px; - color: ${theme('article.title')}; - - &:hover { - color: ${theme('banner.title')}; - font-weight: bold; - cursor: pointer; - text-decoration: underline; - } -` -export const PaymentPic = styled(Img)` - width: 200px; - height: auto; - display: block; -` diff --git a/src/containers/tool/Cashier/styles/payment_sidebar.ts b/src/containers/tool/Cashier/styles/payment_sidebar.ts deleted file mode 100755 index 05dad787b..000000000 --- a/src/containers/tool/Cashier/styles/payment_sidebar.ts +++ /dev/null @@ -1,87 +0,0 @@ -import styled from 'styled-components' - -import type { TActive } from '@/spec' -import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - ${css.column()}; - width: 150px; - border-right: 1px solid; - border-right-color: ${theme('banner.desc')}; - padding: 15px; - padding-bottom: 0; -` -export const TransWrapper = styled.div` - ${css.row('align-center')}; -` -export const AccountIcon = styled(Img)` - ${css.circle(30)}; -` -export const TransIcon = styled(Img)` - fill: ${theme('banner.desc')}; - ${css.size(20)}; - margin-left: 10px; - margin-right: 10px; -` -export const SiteLogo = styled(Img)` - ${css.size(30)}; - margin-top: -5px; -` -export const SelectorWrapper = styled.div` - margin-top: 30px; -` -export const SelectorTitle = styled.div` - color: ${theme('article.title')}; - font-weight: bold; -` -export const TitleDivider = styled.div` - border-bottom: 1px solid; - border-bottom-color: ${theme('article.title')}; - width: 80%; - margin-top: 10px; - margin-bottom: 10px; - opacity: 0.5; -` -const OptionWrapper = styled.div` - ${css.row('align-center')}; - margin-bottom: 8px; - &:hover { - cursor: pointer; - } -` -export const WeixinWrapper = styled(OptionWrapper)` - color: ${({ active }) => (active ? '#3eb64b' : theme('article.title'))}; - display: ${({ show }) => (show ? 'block' : 'none')}; -` -export const AliWrapper = styled(OptionWrapper)` - color: ${({ active }) => (active ? '#42abe1' : theme('article.title'))}; - display: ${({ show }) => (show ? 'block' : 'none')}; -` -export const Holder = styled.div<{ margin?: string }>` - margin-top: ${({ margin }) => margin || '80px'}; -` -export const QuestionWrapper = styled.div` - ${css.row('align-center')}; - color: ${theme('article.digest')}; - &:hover { - color: ${theme('article.title')}; - cursor: pointer; - } -` -export const OptionTitle = styled.span` - margin-left: 6px; -` -export const FaceValueWrapper = styled.div` - color: ${theme('article.digest')}; -` -export const FaceValueNum = styled.span` - color: orange; - font-weight: bold; -` -export const PaymentIcon = styled(Img)` - ${css.size(16)}; -` -export const QuestionIcon = styled(PaymentIcon)` - fill: ${theme('article.digest')}; -` diff --git a/src/containers/tool/Cashier/styles/question_content.ts b/src/containers/tool/Cashier/styles/question_content.ts deleted file mode 100755 index 127a42969..000000000 --- a/src/containers/tool/Cashier/styles/question_content.ts +++ /dev/null @@ -1,30 +0,0 @@ -// -import styled from 'styled-components' - -// import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - ${css.columnGrow()}; - margin-top: 10px; - padding-left: 15px; -` - -export const Title = styled.div` - color: ${theme('article.title')}; - font-weight: bold; -` - -export const Desc = styled.div` - color: ${theme('article.digest')}; - margin-top: 3px; -` - -export const Divider = styled.div` - border-top: 1px solid; - color: ${theme('article.digest')}; - width: 100%; - opacity: 0.4; - margin-top: 8px; - margin-bottom: 8px; -` diff --git a/src/containers/tool/Cashier/styles/question_sidebar.ts b/src/containers/tool/Cashier/styles/question_sidebar.ts deleted file mode 100755 index 811961040..000000000 --- a/src/containers/tool/Cashier/styles/question_sidebar.ts +++ /dev/null @@ -1,29 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - ${css.column()}; - width: 150px; - padding: 10px; -` -export const BackBtnWrapper = styled.div` - ${css.row('align-center')}; - color: ${theme('banner.title')}; - font-size: 1rem; - - &:hover { - cursor: pointer; - } -` -export const BackTitle = styled.span` - margin-left: 5px; -` -export const Holder = styled.div` - margin-top: 100px; -` -export const BackIcon = styled(Img)` - fill: ${theme('banner.title')}; - ${css.size(18)}; -` diff --git a/src/containers/tool/Cashier/styles/sidebar.ts b/src/containers/tool/Cashier/styles/sidebar.ts deleted file mode 100755 index 9ce2c229f..000000000 --- a/src/containers/tool/Cashier/styles/sidebar.ts +++ /dev/null @@ -1,6 +0,0 @@ -import styled from 'styled-components' - -// import Img from '@/Img' - -export const Wrapper = styled.div`` -export const Holder = 1 diff --git a/src/containers/tool/Cashier/tests/index.test.ts b/src/containers/tool/Cashier/tests/index.test.ts deleted file mode 100755 index 8fc877563..000000000 --- a/src/containers/tool/Cashier/tests/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react' -// import { shallow } from 'enzyme' - -// import Cashier from '..' - -describe('TODO ', () => { - it('Expect to have unit tests specified', () => { - expect(true).toEqual(true) - }) -}) diff --git a/src/containers/tool/Cashier/tests/store.test.ts b/src/containers/tool/Cashier/tests/store.test.ts deleted file mode 100755 index f44dcb4c7..000000000 --- a/src/containers/tool/Cashier/tests/store.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Cashier store test - * - */ - -// import Cashier from '..' - -it('TODO: store test Cashier', () => { - expect(1 + 1).toBe(2) -}) diff --git a/src/containers/tool/Drawer/Content/Content.tsx b/src/containers/tool/Drawer/Content/Content.tsx index d104e57b2..9a5d9883f 100644 --- a/src/containers/tool/Drawer/Content/Content.tsx +++ b/src/containers/tool/Drawer/Content/Content.tsx @@ -1,92 +1,108 @@ -import { FC } from 'react' +import { FC, Suspense } from 'react' import TYPE from '@/constant/type' // import ModeLineMenu from '@/containers/unit/ModeLineMenu' -import type { TUser } from '@/spec' - -import type { TExtraInfo } from '../spec' - -import { - ArticleViewer, - MailsViewer, - // editors - AccountEditor, - WallpaperEditor, - // utils - UserLister, - DashboardDesc, - ArticleEditor, - PassportEditor, - TagSettingEditor, - SearchPanel, -} from '../dynamics' + +import ArticleViewer from '@/containers/viewer/ArticleViewer' +import LavaLampLoading from '@/widgets/Loading/LavaLampLoading' + +import TagSettingEditor from '@/containers/editor/TagSettingEditor' +import PassportEditor from '@/containers/editor/PassportEditor' +import ArticleEditor from '@/containers/editor/ArticleEditor' +import WallpaperEditor from '@/containers/editor/WallpaperEditor' +import AccountEditor from '@/containers/editor/AccountEditor' +import MailsViewer from '@/containers/viewer/MailsViewer' + +import UserList from '@/widgets/UserList' +import SearchPanel from '@/widgets/SearchPanel' type TProps = { type: string - attUser: TUser - extraInfo: TExtraInfo } -const Content: FC = ({ type, attUser, extraInfo }) => { - if (!type) return null +const Content: FC = ({ type }) => { + if (!type) return const { DRAWER } = TYPE switch (type) { case DRAWER.SEARCH_PANEL: - return + return ( + }> + + + ) case DRAWER.ACCOUNT_EDIT: - // @ts-ignore - return + return ( + }> + + + ) case DRAWER.PASSPORT_EDITOR: - // @ts-ignore - return + return ( + }> + + + ) case DRAWER.G_EDITOR: - return + return ( + }> + + + ) case DRAWER.MAILS_VIEW: - // @ts-ignore - return - - case DRAWER.DASHBOARD_DESC: { - const { postLayout, dashboardDescLayout } = extraInfo - - const activeSettings = { - postLayout, - } - // @ts-ignore - return - } + return ( + }> + + + ) case DRAWER.CUSTOM_BG_EDITOR: - // @ts-ignore - return + return ( + }> + + + ) case DRAWER.MODELINE_MENU: return null // @ts-ignore // return - case DRAWER.USER_LISTER: { - // @ts-ignore - return + case DRAWER.LIST_USERS: { + return ( + }> + + + + ) } case DRAWER.CREATE_TAG: { - // @ts-ignore - return + return ( + }> + + + ) } case DRAWER.EDIT_TAG: { - // @ts-ignore - return + return ( + }> + + + ) } default: { - // @ts-ignore - return + return ( + }> + + + ) } } } diff --git a/src/containers/tool/Drawer/Content/DesktopView.tsx b/src/containers/tool/Drawer/Content/DesktopView.tsx index 36dabff2f..6726b61ce 100755 --- a/src/containers/tool/Drawer/Content/DesktopView.tsx +++ b/src/containers/tool/Drawer/Content/DesktopView.tsx @@ -1,52 +1,43 @@ import { FC, useEffect, useRef, memo } from 'react' +import { useOverlayScrollbars } from 'overlayscrollbars-react' + import { DRAWER_SCROLLER } from '@/constant/dom' -import CustomScroller from '@/widgets/CustomScroller' +import { scrollDrawerToTop } from '@/dom' +// import CustomScroller from '@/widgets/CustomScroller' -import type { TExtraInfo } from '../spec' import Content from './Content' import { Wrapper } from '../styles/content' -import { isWideMode } from '../styles/metrics' type TProps = { visible: boolean type: string // TODO: - attUser: any // TODO: - extraInfo: TExtraInfo } -const DesktopView: FC = ({ visible, type, attUser, extraInfo }) => { +const DesktopView: FC = ({ visible, type }) => { const ref = useRef(null) - /* - * reset when content visible - * scroll to top always - */ + const options = { + scrollbars: { autoHide: 'leave', autoHideDelay: 300, autoHideSuspend: true }, + } + + // @ts-ignore + const [initialize, instance] = useOverlayScrollbars({ options, defer: false }) + useEffect(() => { - if (visible && ref?.current) { - ref.current.scrollIntoView() + if (initialize && ref?.current) { + initialize(ref?.current) + + const instanceEl = instance?.()?.elements() + const { viewport } = instanceEl + window[DRAWER_SCROLLER] = viewport + scrollDrawerToTop() } - }, [visible, ref]) - - if (isWideMode(type)) { - return ( - - - - - - ) - } + }, [initialize, ref, instance]) return ( - - + + ) } diff --git a/src/containers/tool/Drawer/Content/MobileView.tsx b/src/containers/tool/Drawer/Content/MobileView.tsx index e30fd3dc8..4214b6167 100755 --- a/src/containers/tool/Drawer/Content/MobileView.tsx +++ b/src/containers/tool/Drawer/Content/MobileView.tsx @@ -2,7 +2,7 @@ import { FC, useEffect, useRef, useState, memo } from 'react' import CustomScroller from '@/widgets/CustomScroller' -import type { TSwipeOption, TExtraInfo } from '../spec' +import type { TSwipeOption } from '../spec' import Content from './Content' import { getMobileContentHeight } from '../styles/metrics' import { Wrapper } from '../styles/content' @@ -12,17 +12,9 @@ type TProps = { visible: boolean options: TSwipeOption type: string // TODO - attUser: any // TODO - extraInfo: TExtraInfo } -const MobileView: FC = ({ - visible, - options, - type, - attUser, - extraInfo, -}) => { +const MobileView: FC = ({ visible, options, type }) => { const ref = useRef(null) const [topEnterTimer, setTopEnterTimer] = useState(null) @@ -96,8 +88,8 @@ const MobileView: FC = ({ onBottomLeave={() => toggleSwipeAviliable('up', false)} autoHide > - - + + ) diff --git a/src/containers/tool/Drawer/Content/index.tsx b/src/containers/tool/Drawer/Content/index.tsx index 99223d541..c856a2533 100755 --- a/src/containers/tool/Drawer/Content/index.tsx +++ b/src/containers/tool/Drawer/Content/index.tsx @@ -3,17 +3,21 @@ import dynamic from 'next/dynamic' import useMobileDetect from '@groupher/use-mobile-detect-hook' -const DesktopView = dynamic(() => import('./DesktopView'), { ssr: false }) -const MobileView = dynamic(() => import('./MobileView'), { ssr: false }) +import DesktopView from './DesktopView' +import MobileView from './MobileView' + +// const DesktopView = dynamic(() => import('./DesktopView'), { ssr: false }) +// const MobileView = dynamic(() => import('./MobileView'), { ssr: false }) const Content = (props) => { const { isMobile } = useMobileDetect() - return ( - - {!isMobile ? : } - - ) + // eslint-disable-next-line react/destructuring-assignment + if (!props.visible) { + return null + } + + return {!isMobile ? : } } export default memo(Content) diff --git a/src/containers/tool/Drawer/Viewer/index.tsx b/src/containers/tool/Drawer/Viewer/index.tsx index 4b42737c2..595e325f0 100755 --- a/src/containers/tool/Drawer/Viewer/index.tsx +++ b/src/containers/tool/Drawer/Viewer/index.tsx @@ -1,10 +1,9 @@ import { Fragment } from 'react' -import dynamic from 'next/dynamic' import useMobileDetect from '@groupher/use-mobile-detect-hook' -const DesktopView = dynamic(() => import('./DesktopView'), { ssr: false }) -const MobileView = dynamic(() => import('./MobileView'), { ssr: false }) +import DesktopView from './DesktopView' +import MobileView from './MobileView' /** * @param {object} props diff --git a/src/containers/tool/Drawer/constant.ts b/src/containers/tool/Drawer/constant.ts index c9b754a97..4dabb6678 100755 --- a/src/containers/tool/Drawer/constant.ts +++ b/src/containers/tool/Drawer/constant.ts @@ -3,6 +3,8 @@ import { concat, keys, reduce } from 'ramda' import TYPE from '@/constant/type' import { ARTICLE_THREAD } from '@/constant/thread' +export const NARROW_HEIGHT_OFFSET = 25 + export const ARTICLE_VIEWER_TYPES = reduce( concat, // @ts-ignore diff --git a/src/containers/tool/Drawer/dynamics.tsx b/src/containers/tool/Drawer/dynamics.tsx deleted file mode 100755 index dd003678c..000000000 --- a/src/containers/tool/Drawer/dynamics.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-disable react/display-name */ -import dynamic from 'next/dynamic' - -import LavaLampLoading from '@/widgets/Loading/LavaLampLoading' -// import EditorLoading from '@/widgets/Loading/EditorLoading' - -import { LavaLoadingWrapper } from './styles' - -const CommonLoading = () => { - return ( - - - - ) -} - -// editor style loading config -// const editorConfig = { -// // @ts-ignore -// loading: () => , -// ssr: false, -// } - -// viewers -export const ArticleViewer = dynamic(() => import('@/containers/viewer/ArticleViewer'), { - loading: () => , -}) - -export const MailsViewer = dynamic(() => import('@/containers/viewer/MailsViewer'), { - loading: () => , -}) - -// editors -export const AccountEditor = dynamic(() => import('@/containers/editor/AccountEditor'), { - loading: () => , -}) - -// user lister -export const UserLister = dynamic(() => import('@/containers/user/UserLister'), { - loading: () => , -}) - -export const WallpaperEditor = dynamic(() => import('@/containers/editor/WallpaperEditor'), { - loading: () => , -}) - -export const DashboardDesc = dynamic(() => import('@/widgets/DashboardDesc'), { - loading: () => , -}) - -export const ArticleEditor = dynamic(() => import('@/containers/editor/ArticleEditor'), { - loading: () => , -}) - -export const PassportEditor = dynamic(() => import('@/containers/editor/PassportEditor'), { - loading: () => , -}) - -export const TagSettingEditor = dynamic(() => import('@/containers/editor/TagSettingEditor'), { - loading: () => , -}) - -export const SearchPanel = dynamic(() => import('@/widgets/SearchPanel'), { - loading: () => , -}) diff --git a/src/containers/tool/Drawer/index.tsx b/src/containers/tool/Drawer/index.tsx index 67b74d1e1..4ff017242 100755 --- a/src/containers/tool/Drawer/index.tsx +++ b/src/containers/tool/Drawer/index.tsx @@ -7,10 +7,11 @@ import { FC } from 'react' import { observer } from 'mobx-react-lite' -import type { TMetric } from '@/spec' import { buildLog } from '@/logger' + import useWindowResize from '@/hooks/useWindowResize' import useShortcut from '@/hooks/useShortcut' +import useMetric from '@/hooks/useMetric' import { useStore } from './store' @@ -22,12 +23,9 @@ import { useInit, closeDrawer } from './logic' /* eslint-disable-next-line */ const log = buildLog('C:Preview') -type TProps = { - metric: TMetric -} - -const Drawer: FC = ({ metric }) => { +const Drawer: FC = () => { const store = useStore() + const metric = useMetric() const { width: windowWidth } = useWindowResize() diff --git a/src/containers/tool/Drawer/store.ts b/src/containers/tool/Drawer/store.ts index f0d77dfcc..d7f5ff441 100755 --- a/src/containers/tool/Drawer/store.ts +++ b/src/containers/tool/Drawer/store.ts @@ -161,7 +161,7 @@ const DrawerStore = T.model('DrawerStore', { if (type === DRAWER.MODELINE_MENU) { slf.mmType = data } - if (type === DRAWER.USER_LISTER) { + if (type === DRAWER.LIST_USERS) { slf.userListerType = data } if (type === DRAWER.DASHBOARD_DESC) { @@ -192,7 +192,8 @@ const DrawerStore = T.model('DrawerStore', { type !== DRAWER.CREATE_TAG && type !== DRAWER.PASSPORT_EDITOR && type !== DRAWER.EDIT_TAG && - type !== DRAWER.SEARCH_PANEL + type !== DRAWER.SEARCH_PANEL && + type !== DRAWER.LIST_USERS ) { slf.markPreviewURLIfNeed(data) } diff --git a/src/containers/tool/Drawer/styles/content/index.ts b/src/containers/tool/Drawer/styles/content/index.ts index 7234dc051..811330719 100755 --- a/src/containers/tool/Drawer/styles/content/index.ts +++ b/src/containers/tool/Drawer/styles/content/index.ts @@ -1,16 +1,14 @@ import styled from 'styled-components' -import css from '@/css' +import { NARROW_HEIGHT_OFFSET } from '../../constant' +import { isWideMode } from '../metrics' +// import css from '@/css' -export const Wrapper = styled.div` +export const Wrapper = styled.div<{ type: string }>` width: 100%; - /* NOTE: those property must exist otherwise custom scroller will not work*/ - height: 100%; - - /* 30px is the modeLine height */ - ${css.media.mobile` - height: auto; - `}; + height: ${({ type }) => + isWideMode(type) ? '100vh' : `calc(100vh - ${NARROW_HEIGHT_OFFSET * 2}px)`}; + overflow-y: scroll; ` -export const holder = 1 +export const InnerWrapper = styled.div`` diff --git a/src/containers/tool/Drawer/styles/index.ts b/src/containers/tool/Drawer/styles/index.ts index bbd2055ec..ad85c750a 100755 --- a/src/containers/tool/Drawer/styles/index.ts +++ b/src/containers/tool/Drawer/styles/index.ts @@ -5,6 +5,7 @@ import css, { theme, zIndex } from '@/css' import { pixelAdd } from '@/dom' import type { TDrawer, TSwipe } from '../spec' +import { NARROW_HEIGHT_OFFSET } from '../constant' import { getTransform, getMobileContentHeight, @@ -93,7 +94,8 @@ export const DrawerContent = styled.div<{ type: string }>` position: relative; width: 100%; background-color: ${theme('drawer.bg')}; - height: ${({ type }) => (isWideMode(type) ? '100vh' : 'calc(100vh - 50px)')}; + height: ${({ type }) => + isWideMode(type) ? '100vh' : `calc(100vh - ${NARROW_HEIGHT_OFFSET * 2}px)`}; border-radius: ${({ type }) => (isWideMode(type) ? 0 : '10px')}; box-shadow: ${({ type }) => isWideMode(type) ? theme('drawer.shadow') : theme('drawer.shadowLite')}; diff --git a/src/containers/user/UserLister/HeaderInfo.tsx b/src/containers/user/UserLister/HeaderInfo.tsx deleted file mode 100755 index 73943d46a..000000000 --- a/src/containers/user/UserLister/HeaderInfo.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { FC, memo } from 'react' - -import type { TCommunity } from '@/spec' -import { ICON_CMD, EMAIL_SUPPORT } from '@/config' -import TYPE from '@/constant/type' - -import NoticeBar from '@/widgets/NoticeBar' - -import { Wrapper, Title, DescLabel, DescIcon, DescText, DescLink } from './styles/header_info' - -type TProps = { - type: string - totalCount: number - curCommunity: TCommunity -} - -const HeaderInfo: FC = ({ type, totalCount, curCommunity }) => { - switch (type) { - case TYPE.USER_LISTER_FAVORITES: - return ( - - - 已收藏用户 ({totalCount} - 人) - - - - -- - - - ) - - case TYPE.USER_LISTER_STARS: - return ( - - - 已赞用户 ({totalCount} - 人) - - - - -- - - - ) - - case TYPE.USER_LISTER_FOLLOWERS: - return ( - - - 关注者 ({totalCount} - 人) - - - 关注 -- 的人 - - - ) - - case TYPE.USER_LISTER_FOLLOWINGS: - return ( - - - 关注中 ({totalCount} - 人) - - - -- 关注的人 - - - ) - - case TYPE.USER_LISTER_COMMUNITY_SUBSCRIBERS: - return ( - - - 已加入 ({totalCount} - 人) - - - 他们加入了 {curCommunity.title} 社区 - - - ) - - case TYPE.USER_LISTER_COMMUNITY_EDITORS: - return ( - - - {curCommunity.title} 社区志愿者 ({totalCount} - 人) - - - - - 申请成为社区志愿者 - - - - ) - - default: - return WTF ? - } -} - -export default memo(HeaderInfo) diff --git a/src/containers/user/UserLister/List/EditorLayout.tsx b/src/containers/user/UserLister/List/EditorLayout.tsx deleted file mode 100755 index 214b1667a..000000000 --- a/src/containers/user/UserLister/List/EditorLayout.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { FC, memo } from 'react' - -import type { TUser } from '@/spec' - -import useAccount from '@/hooks/useAccount' -import FollowButton from '@/widgets/Buttons/FollowButton' - -import { - Wrapper, - UserWrapper, - UserAvatar, - UserBrief, - Title, - Desc, - Nickname, - Location, - CityIcon, - City, - Action, -} from '../styles/list/editor_layout' -import { onFollow, undoFollow } from '../logic' - -type TProps = { - users: TUser[] -} - -const EditorLayout: FC = ({ users }) => { - const accountInfo = useAccount() - - return ( - - {users.map((user) => ( - - - - - <Nickname href={`/u/${user.login}`}>{user.nickname}</Nickname> - <Location> - <CityIcon /> - <City>{user.location || user.geoCity || '--'}</City> - </Location> - - {user.bio} - - {!!accountInfo && accountInfo.login === user.login ? ( -
(本尊)
- ) : ( - - )} -
-
-
- ))} -
- ) -} - -export default memo(EditorLayout) diff --git a/src/containers/user/UserLister/List/NormalLayout.tsx b/src/containers/user/UserLister/List/NormalLayout.tsx deleted file mode 100755 index 98fe0bb96..000000000 --- a/src/containers/user/UserLister/List/NormalLayout.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { FC, memo } from 'react' - -import type { TUser } from '@/spec' - -import useAccount from '@/hooks/useAccount' -import { cutRest } from '@/fmt' -import FollowButton from '@/widgets/Buttons/FollowButton' - -import { - Wrapper, - UserWrapper, - UserAvatar, - UserBrief, - Title, - Nickname, - Location, - City, - CityIcon, - Action, -} from '../styles/list/normal_layout' -import { onFollow, undoFollow } from '../logic' - -type TProps = { - users: TUser[] -} - -const NormalLayout: FC = ({ users }) => { - const accountInfo = useAccount() - - return ( - - {users.map((user) => ( - - - - - <Nickname href={`/u/${user.login}`} prefetch={false}> - {cutRest(user.nickname, 15)} - </Nickname> - <Location> - <CityIcon /> - <City>{user.location || user.geoCity || '--'}</City> - </Location> - - - {!!accountInfo && accountInfo.login === user.login ? ( -
(本尊)
- ) : ( - - )} -
-
-
- ))} -
- ) -} - -export default memo(NormalLayout) diff --git a/src/containers/user/UserLister/List/index.tsx b/src/containers/user/UserLister/List/index.tsx deleted file mode 100755 index cf3e65f16..000000000 --- a/src/containers/user/UserLister/List/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * UserList - * - */ - -import { FC, memo } from 'react' - -import type { TPagedUsers } from '@/spec' -import TYPE from '@/constant/type' - -import { buildLog } from '@/logger' - -import Pagi from '@/widgets/Pagi' -import EditorLayout from './EditorLayout' -import NormalLayout from './NormalLayout' - -import { onPageChange } from '../logic' - -/* eslint-disable-next-line */ -const log = buildLog('w:UserList:index') - -type TProps = { - type: string - data: TPagedUsers -} - -const UserList: FC = ({ type, data: { entries, pageNumber, pageSize, totalCount } }) => ( - <> - {type === TYPE.USER_LISTER_COMMUNITY_EDITORS ? ( - - ) : ( - - )} - -
- -
-
- -) - -export default memo(UserList) diff --git a/src/containers/user/UserLister/index.tsx b/src/containers/user/UserLister/index.tsx deleted file mode 100755 index 9597c2cc9..000000000 --- a/src/containers/user/UserLister/index.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * UserLister - * - */ - -import { FC } from 'react' -import { observer } from 'mobx-react-lite' - -import TYPE from '@/constant/type' -import { buildLog } from '@/logger' - -import EmptyLabel from '@/widgets/EmptyLabel' -import LavaLampLoading from '@/widgets/Loading/LavaLampLoading' - -import { useStore } from './store' -import HeaderInfo from './HeaderInfo' -import List from './List' - -import { Wrapper, MsgWrapper } from './styles' -import { useInit } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:UserLister') - -const renderContent = (type, curView, pagedUsersData) => { - switch (curView) { - case TYPE.LOADING: - return ( - - - - ) - - case TYPE.RESULT_EMPTY: - return ( - - - - ) - - default: - return - } -} - -type TProps = { - type: string -} - -const UserLister: FC = ({ type }) => { - const store = useStore() - useInit(store, type) - - const { curView, pagedUsersData, curCommunity } = store - - return ( - - - - {renderContent(type, curView, pagedUsersData)} - - ) -} - -export default observer(UserLister) diff --git a/src/containers/user/UserLister/logic.ts b/src/containers/user/UserLister/logic.ts deleted file mode 100755 index e0d1ce652..000000000 --- a/src/containers/user/UserLister/logic.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { useEffect } from 'react' - -import { PAGE_SIZE } from '@/config' -import ERR from '@/constant/err' -import EVENT from '@/constant/event' -import TYPE from '@/constant/type' - -import { errRescue } from '@/signal' -import { buildLog } from '@/logger' -import asyncSuit from '@/async' - -import type { TStore } from './store' -import S from './schema' - -/* eslint-disable-next-line */ -const log = buildLog('L:UserLister') - -const { SR71, $solver, asyncRes, asyncErr } = asyncSuit -const sr71$ = new SR71({ - // @ts-ignore - receive: [EVENT.USER_LISTER_OPEN], -}) - -let sub$ = null -let store: TStore | undefined - -export const onFollow = (login: string): void => sr71$.mutate(S.follow, { login }) -export const undoFollow = (login: string): void => sr71$.mutate(S.undoFollow, { login }) - -const loadUsers = (type, page = 1): void => { - // log('loadUsers type: ', type) - - // TODO: use simple loading - store.mark({ curView: TYPE.LOADING }) - switch (type) { - case TYPE.USER_LISTER_COMMUNITY_EDITORS: { - const { id } = store.curCommunity - const args = { - id, - filter: { page, size: PAGE_SIZE.D }, - userHasLogin: store.isLogin, - } - - return sr71$.query(S.pagedCommunityEditors, args) - } - case TYPE.USER_LISTER_COMMUNITY_SUBSCRIBERS: { - const { id } = store.curCommunity - const args = { - id, - filter: { page, size: PAGE_SIZE.D }, - userHasLogin: store.isLogin, - } - - return sr71$.query(S.pagedCommunitySubscribers, args) - } - default: { - return sr71$.query(S.pagedUsers, { - filter: { page, size: PAGE_SIZE.D }, - }) - } - } -} - -export const onPageChange = (page = 1): void => { - const { type } = store - loadUsers(type, page) -} - -const handleUsersRes = (pagedUsers) => { - const curView = pagedUsers.totalCount === 0 ? TYPE.RESULT_EMPTY : TYPE.RESULT - store.mark({ pagedUsers, curView }) -} -// ############################### -// Data & Error handlers -// ############################### -const DataSolver = [ - { - match: asyncRes('reactionUsers'), - action: ({ reactionUsers: pagedUsers }) => handleUsersRes(pagedUsers), - }, - { - match: asyncRes('pagedFollowings'), - action: ({ pagedFollowings: pagedUsers }) => handleUsersRes(pagedUsers), - }, - { - match: asyncRes('pagedFollowers'), - action: ({ pagedFollowers: pagedUsers }) => handleUsersRes(pagedUsers), - }, - { - match: asyncRes('pagedCommunityEditors'), - action: ({ pagedCommunityEditors: pagedUsers }) => handleUsersRes(pagedUsers), - }, - { - match: asyncRes('pagedCommunitySubscribers'), - action: ({ pagedCommunitySubscribers: pagedUsers }) => handleUsersRes(pagedUsers), - }, - { - match: asyncRes('pagedUsers'), - action: ({ pagedUsers }) => handleUsersRes(pagedUsers), - }, - { - match: asyncRes('follow'), - action: ({ follow: { login } }) => store.toggleHasFollow(login), - }, - { - match: asyncRes('undoFollow'), - action: ({ undoFollow: { login } }) => store.toggleHasFollow(login), - }, -] -const ErrSolver = [ - { - match: asyncErr(ERR.GRAPHQL), - action: () => { - // - }, - }, - { - match: asyncErr(ERR.TIMEOUT), - action: ({ details }) => errRescue({ type: ERR.TIMEOUT, details, path: 'UserLister' }), - }, - { - match: asyncErr(ERR.NETWORK), - action: () => errRescue({ type: ERR.NETWORK, path: 'UserLister' }), - }, -] - -// ############################### -// init & uninit -// ############################### -export const useInit = (_store: TStore, type: string): void => { - useEffect(() => { - store = _store - // log('effect init') - sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) - loadUsers(type) - - return () => { - // log('effect uninit') - sr71$.stop() - sub$.unsubscribe() - } - }, [_store, type]) -} diff --git a/src/containers/user/UserLister/schema.ts b/src/containers/user/UserLister/schema.ts deleted file mode 100755 index 4e093ed35..000000000 --- a/src/containers/user/UserLister/schema.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { gql } from 'urql/core' -import { F, P } from '@/schemas' - -const pagedUsers = gql` - query($filter: PagedUsersFilter!) { - pagedUsers(filter: $filter) { - entries { - ${F.author} - location - } - ${F.pagi} - } - } -` - -const pagedCommunitySubscribers = gql` - query($id: ID, $community: String, $filter: PagiFilter!, $userHasLogin: Boolean!) { - pagedCommunitySubscribers(id: $id, community: $community, filter: $filter) { - entries { - ${F.author} - location - viewerHasFollowed @include(if: $userHasLogin) - } - ${F.pagi} - } - } -` - -const pagedFollowers = gql` - query($userId: ID, $filter: PagiFilter!, $userHasLogin: Boolean!) { - pagedFollowers(userId: $userId, filter: $filter) { - entries { - ${F.author} - location - viewerHasFollowed @include(if: $userHasLogin) - } - totalCount - } - } -` - -const pagedFollowings = gql` - query($userId: ID, $filter: PagiFilter!, $userHasLogin: Boolean!) { - pagedFollowings(userId: $userId, filter: $filter) { - entries { - ${F.author} - location - viewerHasFollowed @include(if: $userHasLogin) - } - totalCount - } - } -` -const pagedCommunityEditors = gql` - query($id: ID!, $filter: PagiFilter!, $userHasLogin: Boolean!) { - pagedCommunityEditors(id: $id, filter: $filter) { - entries { - ${F.author} - location - viewerHasFollowed @include(if: $userHasLogin) - } - ${F.pagi} - } - } -` - -const follow = gql` - ${P.follow} -` - -const undoFollow = gql` - ${P.undoFollow} -` - -const schema = { - pagedUsers, - pagedCommunitySubscribers, - pagedFollowers, - pagedFollowings, - pagedCommunityEditors, - - follow, - undoFollow, -} - -export default schema diff --git a/src/containers/user/UserLister/store.ts b/src/containers/user/UserLister/store.ts deleted file mode 100755 index 1f0e0e126..000000000 --- a/src/containers/user/UserLister/store.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * UserLister store - * - */ - -import { findIndex, propEq } from 'ramda' - -import type { TRootStore, TCommunity, TPagedUsers, TAccount } from '@/spec' -import TYPE from '@/constant/type' -import { T, getParent, markStates, Instance, toJS, useMobxContext } from '@/mobx' -import { PagedUsers, emptyPagi } from '@/model' - -const UserLister = T.model('UserLister', { - loading: T.opt(T.bool, false), - curView: T.opt(T.enum('curView', [TYPE.RESULT, TYPE.LOADING, TYPE.RESULT_EMPTY]), TYPE.LOADING), - pagedUsers: T.opt(PagedUsers, emptyPagi), - type: T.opt( - T.enum('type', [ - TYPE.USER_LISTER_FAVORITES, - TYPE.USER_LISTER_STARS, - TYPE.USER_LISTER_COMMUNITY_EDITORS, - TYPE.USER_LISTER_COMMUNITY_SUBSCRIBERS, - TYPE.USER_LISTER_FOLLOWINGS, - TYPE.USER_LISTER_FOLLOWERS, - ]), - TYPE.USER_LISTER_FAVORITES, - ), - id: T.maybeNull(T.string), - thread: T.maybeNull(T.string), - action: T.maybeNull(T.string), - brief: T.opt(T.string, ''), -}) - .views((self) => ({ - get isLogin(): boolean { - const root = getParent(self) as TRootStore - return root.account.isLogin - }, - get accountInfo(): TAccount { - const root = getParent(self) as TRootStore - return root.accountInfo - }, - get pagedUsersData(): TPagedUsers { - return toJS(self.pagedUsers) - }, - get curCommunity(): TCommunity { - const root = getParent(self) as TRootStore - return toJS(root.viewing.community) - }, - })) - .actions((self) => ({ - reset(): void { - // - }, - toggleHasFollow(login: string): void { - const { entries } = self.pagedUsersData - - // @ts-ignore - const index = findIndex(propEq(login, 'login'), entries) - if (index < 0) return - - const curIsFollow = self.pagedUsers.entries[index].viewerHasFollowed - self.pagedUsers.entries[index].viewerHasFollowed = !curIsFollow - }, - mark(sobj: Record): void { - markStates(sobj, self) - }, - })) - -export type TStore = Instance -export const useStore = (): TStore => useMobxContext().store.userLister - -export default UserLister diff --git a/src/containers/user/UserLister/styles/header_info.ts b/src/containers/user/UserLister/styles/header_info.ts deleted file mode 100755 index d9dd6235d..000000000 --- a/src/containers/user/UserLister/styles/header_info.ts +++ /dev/null @@ -1,39 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - ${css.column()}; - margin-bottom: 12px; - margin-left: 4px; -` -export const Title = styled.div` - color: ${theme('article.title')}; - font-size: 1rem; - margin-bottom: 3px; -` -export const DescLabel = styled.div` - ${css.row('align-center')}; -` -export const DescIcon = styled(Img)` - fill: ${theme('article.digest')}; - ${css.size(12)}; - margin-right: 5px; -` -export const DescLink = styled.a` - color: #139c9e; - text-decoration: none; - margin-left: 25px; - - &:hover { - color: #139c9e; - cursor: pointer; - text-decoration: underline; - } - transition: color 0.2s; -` -export const DescText = styled.div` - color: ${theme('article.digest')}; - font-size: 0.9rem; -` diff --git a/src/containers/user/UserLister/styles/index.ts b/src/containers/user/UserLister/styles/index.ts deleted file mode 100755 index 5a452dff4..000000000 --- a/src/containers/user/UserLister/styles/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import styled from 'styled-components' - -import css from '@/css' - -export const Wrapper = styled.div` - height: 600px; - padding: 20px; -` -export const MsgWrapper = styled.div` - ${css.row('align-both')}; - width: 90%; - height: 180px; -` diff --git a/src/containers/user/UserLister/styles/list/editor_layout.ts b/src/containers/user/UserLister/styles/list/editor_layout.ts deleted file mode 100755 index d3e4829e8..000000000 --- a/src/containers/user/UserLister/styles/list/editor_layout.ts +++ /dev/null @@ -1,97 +0,0 @@ -import Link from 'next/link' -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' -import CitySVG from '@/icons/City' - -export const Wrapper = styled.div`` - -export const UserWrapper = styled.div` - ${css.row()}; - width: 100%; - margin-bottom: 10px; - margin-right: 5px; - padding: 20px 10px; - border-bottom: 1px solid; - border-bottom-color: ${theme('divider')}; -` -export const UserAvatar = styled(Img)` - ${css.size(55)}; - border-radius: 42%; - margin-top: 5px; - - ${css.media.mobile` - ${css.size(30)}; -`}; -` -export const UserBrief = styled.div` - ${css.columnGrow('justify-between')}; - margin-left: 24px; -` -export const Title = styled.div` - ${css.row('align-center')}; - color: ${theme('article.title')}; - - ${css.media.tablet` - ${css.column('align-start')}; - `}; -` -export const Desc = styled.div` - font-size: 15px; - margin-top: 2px; - margin-bottom: 5px; - color: ${theme('article.digest')}; -` -export const Nickname = styled(Link)` - color: ${theme('article.title')}; - text-decoration: none; - font-size: 16px; - - &:hover { - color: ${theme('article.title')}; - text-decoration: underline; - } -` -export const Location = styled.div` - ${css.row('align-center')}; - color: ${theme('article.digest')}; - margin-left: 10px; - opacity: 0.8; - - ${css.media.tablet` - ${css.cutRest('80px')}; - margin-left: 0; - margin-bottom: 3px; - `}; - - ${css.media.mobile` - ${css.cutRest('60px')}; - margin-left: 0; - margin-bottom: 3px; - `}; -` -export const City = styled.div` - ${css.cutRest('200px')}; - ${css.media.tablet` - ${css.cutRest('80px')}; - margin-left: 0; - margin-bottom: 3px; - `}; - - ${css.media.mobile` - ${css.cutRest('60px')}; - margin-left: 0; - margin-bottom: 3px; - `}; -` -export const CityIcon = styled(CitySVG)` - fill: ${theme('article.digest')}; - ${css.size(13)}; - margin-right: 2px; -` -export const Action = styled.div` - color: ${theme('article.digest')}; - width: 100px; - margin-top: 5px; -` diff --git a/src/containers/user/UserLister/styles/list/normal_layout.ts b/src/containers/user/UserLister/styles/list/normal_layout.ts deleted file mode 100755 index d84dad21d..000000000 --- a/src/containers/user/UserLister/styles/list/normal_layout.ts +++ /dev/null @@ -1,78 +0,0 @@ -import Link from 'next/link' -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' -import CitySVG from '@/icons/City' - -export const Wrapper = styled.div` - ${css.rowWrap()}; -` - -export const UserWrapper = styled.div` - ${css.row()}; - width: 48%; - margin-bottom: 10px; - margin-right: 5px; - padding-top: 10px; - padding-bottom: 10px; - border-bottom: 1px solid; - border-bottom-color: ${theme('divider')}; -` -export const UserAvatar = styled(Img)` - ${css.size(32)}; - border-radius: 42%; - margin-top: 4px; - - ${css.media.mobile` - ${css.size(30)}; -`}; -` -export const UserBrief = styled.div` - ${css.columnGrow('justify-between')}; - margin-left: 18px; -` -export const Title = styled.div` - ${css.media.tablet` - ${css.column('align-start')}; - `}; -` -export const Nickname = styled(Link)` - color: ${theme('article.title')}; - text-decoration: none; - font-size: 16px; - - &:hover { - color: ${theme('article.title')}; - text-decoration: underline; - } -` -export const Location = styled.div` - ${css.row('align-center')}; - color: ${theme('article.digest')}; -` -export const City = styled.div` - ${css.cutRest('150px')}; - ${css.media.tablet` - ${css.cutRest('80px')}; - margin-left: 0; - margin-bottom: 3px; - `}; - - ${css.media.mobile` - ${css.cutRest('60px')}; - margin-left: 0; - margin-bottom: 3px; - `}; -` -export const CityIcon = styled(CitySVG)` - fill: ${theme('article.digest')}; - ${css.size(13)}; - margin-right: 2px; -` -export const Action = styled.div` - color: ${theme('article.digest')}; - width: 100px; - margin-top: 10px; - margin-bottom: 10px; -` diff --git a/src/containers/user/UserLister/styles/user_list.ts b/src/containers/user/UserLister/styles/user_list.ts deleted file mode 100755 index aa0409e2c..000000000 --- a/src/containers/user/UserLister/styles/user_list.ts +++ /dev/null @@ -1,67 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -export const TableWrapper = styled.div` - ${css.rowWrap()}; -` -export const UserWrapper = styled.div` - ${css.row()}; - width: 48%; - margin-bottom: 10px; - margin-right: 5px; - padding-top: 10px; - padding-bottom: 10px; - border-bottom: 1px solid; - border-bottom-color: ${theme('divider')}; -` -export const UserAvatar = styled(Img)` - ${css.size(55)}; - border-radius: 4px; - - ${css.media.mobile` - ${css.size(30)}; -`}; -` -export const UserBrief = styled.div` - ${css.columnGrow('justify-between')}; - margin-left: 18px; -` -export const Title = styled.div` - ${css.row('align-center')}; - color: ${theme('article.title')}; - - ${css.media.tablet` - ${css.column('align-start')}; - `}; -` -export const Nickname = styled.div` - font-size: 1rem; -` -export const Location = styled.div` - ${css.row('align-center')}; - color: ${theme('article.digest')}; - margin-left: 10px; - - ${css.media.tablet` - ${css.cutRest('80px')}; - margin-left: 0; - margin-bottom: 3px; - `}; - - ${css.media.mobile` - ${css.cutRest('60px')}; - margin-left: 0; - margin-bottom: 3px; - `}; -` -export const GeoIcon = styled(Img)` - fill: ${theme('article.digest')}; - ${css.size(13)}; - margin-right: 2px; -` -export const Action = styled.div` - color: ${theme('article.digest')}; - width: 100px; -` diff --git a/src/containers/user/UserLister/tests/index.test.ts b/src/containers/user/UserLister/tests/index.test.ts deleted file mode 100755 index 874f45ee0..000000000 --- a/src/containers/user/UserLister/tests/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react' -// import { shallow } from 'enzyme' - -// import UserLister from '..' - -describe('TODO ', () => { - it('Expect to have unit tests specified', () => { - expect(true).toEqual(true) - }) -}) diff --git a/src/containers/user/UserLister/tests/store.test.ts b/src/containers/user/UserLister/tests/store.test.ts deleted file mode 100755 index 0450e57f9..000000000 --- a/src/containers/user/UserLister/tests/store.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * UserLister store test - * - */ - -// import UserLister from '..' - -it('TODO: store test UserLister', () => { - expect(1 + 1).toBe(2) -}) diff --git a/src/hooks/useCustomScroll.ts b/src/hooks/useCustomScroll.ts deleted file mode 100755 index 27fe5ac74..000000000 --- a/src/hooks/useCustomScroll.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { useEffect, useState, RefObject } from 'react' -import { OverlayScrollbars } from 'overlayscrollbars' - -import THEME from '@/constant/theme' - -type TOption = { - className?: string - themeCategory?: string - scrollbars?: { - autoHide?: 'scroll' | 'never' // string - } - callbacks?: { - onScroll?: () => void - onScrollStart?: () => void - onScrollStop?: () => void - } - // 如果传入 instanceKey, 那么会赋给 window 一个对应的 OverlayScrollbars 对象用来操作定位到某个元素 - // 因为全局使用了 OverlayScrollbars, 常规的 scrollerTo 不会起作用 - // see: https://github.com/KingSora/OverlayScrollbars/issues/100 - instanceKey?: string - // more callbacks see overlayscrollbars docs -} - -/** - * options detail see: - * https://kingsora.github.io/OverlayScrollbars/#!documentation/options - * - * @returns - */ -const useCustomScroll = (ref: RefObject, option: TOption = {}): any => { - const [scrollInstance, setScrollInstance] = useState(null) - - useEffect(() => { - if (OverlayScrollbars && ref.current && !scrollInstance) { - option.className = option.themeCategory === THEME.NIGHT ? 'os-theme-dark' : 'os-theme-light' - delete option.themeCategory - - const defaultOption = { - scrollbars: { autoHide: 'scroll' }, - className: 'os-theme-light', - callbacks: { ...option.callbacks }, - } - const { instanceKey, ...restOptions } = option - const instance = OverlayScrollbars(ref.current, Object.assign(defaultOption, restOptions)) - - if (instanceKey && typeof window === 'object') { - window[instanceKey] = instance.elements().viewport - } - setScrollInstance(instance) - } - // Empty array ensures that effect is only run on mount and unmount - }, [ref, option, scrollInstance]) - - return scrollInstance -} - -export default useCustomScroll diff --git a/src/hooks/useUserListModal.ts b/src/hooks/useUserListModal.ts new file mode 100644 index 000000000..f37f7c693 --- /dev/null +++ b/src/hooks/useUserListModal.ts @@ -0,0 +1,25 @@ +import { useContext } from 'react' +import { MobXProviderContext } from 'mobx-react' + +/** + * NOTE: should use observer to wrap the component who use this hook + */ +type TRes = { + show: boolean + onClose: () => void +} + +const useUserListModal = (): TRes => { + const { store } = useContext(MobXProviderContext) + + if (store === null) { + throw new Error('Store cannot be null, please add a context provider') + } + + return { + show: store.mushroom.showUserListModal, + onClose: () => store.mushroom.closeUserListModal(), + } +} + +export default useUserListModal diff --git a/src/stores/ArticlesStore/index.ts b/src/stores/ArticlesStore/index.ts index 80299c5b2..dfcfeaed1 100644 --- a/src/stores/ArticlesStore/index.ts +++ b/src/stores/ArticlesStore/index.ts @@ -24,7 +24,7 @@ import { ARTICLE_THREAD } from '@/constant/thread' import { plural } from '@/fmt' -import { PagedPosts, PagedChangelogs, ArticlesFilter, emptyPagi } from '@/model' +import { PagedPosts, PagedChangelogs, emptyPagi } from '@/model' const ArticlesStore = T.model('Articles', { pagedPosts: T.opt(PagedPosts, emptyPagi), @@ -39,7 +39,6 @@ const ArticlesStore = T.model('Articles', { activeCat: T.maybeNull(T.enum(values(ARTICLE_CAT))), activeState: T.maybeNull(T.enum(values(ARTICLE_STATE))), - filters: T.opt(ArticlesFilter, {}), resState: T.opt(T.enum('resState', values(TYPE.RES_STATE)), TYPE.RES_STATE.EMPTY), }) .views((self) => ({ @@ -73,10 +72,9 @@ const ArticlesStore = T.model('Articles', { const slf = self as TStore if (!includes(slf.curThread, values(ARTICLE_THREAD))) return false - const curFilter = toJS(pickBy((v) => !isEmpty(v), self.filters)) const pagedPosts = toJS(slf.pagedPosts) - return !isEmpty(curFilter) || !isEmpty(pagedPosts.entries) + return !isEmpty(pagedPosts.entries) }, get pagedArticleKey(): string { const slf = self as TStore diff --git a/src/stores/Model/ArticlesFilter.ts b/src/stores/Model/ArticlesFilter.ts deleted file mode 100755 index 82faa6feb..000000000 --- a/src/stores/Model/ArticlesFilter.ts +++ /dev/null @@ -1,27 +0,0 @@ -import FILTER from '@/constant/filter' -import { T } from '@/mobx' - -export const ArticlesFilter = T.model('ArticlesFilter', { - when: T.opt( - T.enum('when', ['', FILTER.TODAY, FILTER.THIS_WEEK, FILTER.THIS_MONTH, FILTER.THIS_YEAR]), - '', - ), - - sort: T.opt( - T.enum('sort', [ - '', - FILTER.MOST_VIEWS, - FILTER.MOST_FAVORITES, - FILTER.MOST_STARS, - FILTER.MOST_COMMENTS, - FILTER.MOST_GITHUB_STAR, - FILTER.MOST_GITHUB_FORK, - FILTER.MOST_GITHUB_WATCH, - ]), - '', - ), - length: T.opt(T.enum('length', ['', FILTER.MOST_WORDS, FILTER.LEAST_WORDS]), ''), - read: T.opt(T.enum('read', ['', FILTER.READ, FILTER.UNREAD]), ''), -}) - -export const holder = 1 diff --git a/src/stores/Model/index.ts b/src/stores/Model/index.ts index 1eb111b5d..0a7ed47e4 100755 --- a/src/stores/Model/index.ts +++ b/src/stores/Model/index.ts @@ -17,8 +17,6 @@ export { emptyPagi } from './helper/common' export { SimpleUser } from './Common' export { EmptyUser, EmptyAchievement, User, PagedUsers } from './User' -export { ArticlesFilter } from './ArticlesFilter' - export { MailStatus, MentionMsg, PagedMentionMessages } from './Mail' export const Mention = T.model('Mention', { diff --git a/src/stores/RootStore/index.ts b/src/stores/RootStore/index.ts index 4ccae8097..d7bf50943 100755 --- a/src/stores/RootStore/index.ts +++ b/src/stores/RootStore/index.ts @@ -47,8 +47,6 @@ import { AccountEditorStore, MailBoxStore, TagsBarStore, - UserListerStore, - CashierStore, // GEN: IMPORT SUBSTORE PassportEditorStore, @@ -121,8 +119,6 @@ const rootStore = T.model({ // threads tagsBar: T.opt(TagsBarStore, {}), - userLister: T.opt(UserListerStore, {}), - cashier: T.opt(CashierStore, {}), // viewers (for drawer usage) mailsViewer: T.opt(MailsViewerStore, {}), diff --git a/src/stores/index.ts b/src/stores/index.ts index 34554e946..9bbd6d2fe 100755 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -25,9 +25,6 @@ export { default as DrawerStore } from '@/containers/tool/Drawer/store' // export { default as HeaderStore } from '@/containers/unit/Header/store' export { default as MailBoxStore } from '@/containers/tool/MailBox/store' -export { default as UserListerStore } from '@/containers/user/UserLister/store' -export { default as CashierStore } from '@/containers/tool/Cashier/store' - // // contents store diff --git a/src/widgets/AccountUnit/index.tsx b/src/widgets/AccountUnit/index.tsx index c810019ad..fd7758fef 100644 --- a/src/widgets/AccountUnit/index.tsx +++ b/src/widgets/AccountUnit/index.tsx @@ -15,6 +15,7 @@ import useAvatarLayout from '@/hooks/useAvatarLayout' import useBannerLayout from '@/hooks/useBannerLayout' import { BANNER_LAYOUT } from '@/constant/layout' +import ImgFallback from '@/widgets/ImgFallback' import { SpaceGrow } from '@/widgets/Common' import ThemeSwitch from '@/widgets/ThemeSwitch' @@ -28,7 +29,8 @@ type TProps = { } & TSpace const AccountUnit: FC = ({ withName = false, ...restProps }) => { - const { isLogin, avatar, nickname } = useAccount() + const user = useAccount() + const { isLogin, avatar, nickname } = user const avatarLayout = useAvatarLayout() const bannerLayout = useBannerLayout() @@ -42,7 +44,15 @@ const AccountUnit: FC = ({ withName = false, ...restProps }) => { )} - {isLogin ? : } + {isLogin ? ( + } + /> + ) : ( + + )} {!isLogin && withName && 未登入} {isLogin && withName && {nickname}} diff --git a/src/widgets/CustomScroller/HorizontalScroller.tsx b/src/widgets/CustomScroller/HorizontalScroller.tsx deleted file mode 100755 index 57950e71c..000000000 --- a/src/widgets/CustomScroller/HorizontalScroller.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * HorizontalScroller - * - */ - -import { FC, useState, useRef, useCallback, memo } from 'react' -import { Waypoint } from 'react-waypoint' - -import useCustomScroll from '@/hooks/useCustomScroll' -// import ViewportTracker from '@/widgets/ViewportTracker' -import SIZE from '@/constant/size' -import useTheme from '@/hooks/useTheme' - -import type { TProps as TScrollProps } from '.' - -import { - Wrapper, - // - ScrollWrapper, - InnerWrapper, - LeftShadowBar, - RightShadowBar, -} from './styles/horizontal_scroller' - -type TProps = Omit< - TScrollProps, - | 'direction' - | 'onTopEnter' - | 'onTopLeave' - | 'onBottomEnter' - | 'onBottomLeave' - | 'onScrollDirectionChange' -> - -// horizontal version -const HorizontalScroller: FC = ({ - height = '100%', - width = '100%', - innerHeight = '100%', - showShadow = true, - shadowSize = SIZE.SMALL, - barSize = SIZE.SMALL, - children, - autoHide = true, - withBorder = false, -}) => { - const [showLeftShadow, setShowLeftShadow] = useState(false) - const [showRightShadow, setShowRightShadow] = useState(true) - - const handleShowLeftShadow = useCallback(() => setShowLeftShadow(true), []) - const handleHideLeftShadow = useCallback(() => setShowLeftShadow(false), []) - - const handleShowRightShadow = useCallback(() => setShowRightShadow(true), []) - const handleHideRightShadow = useCallback(() => setShowRightShadow(false), []) - - // @ts-ignore - const { themeMap } = useTheme() - const { _meta: themeMeta } = themeMap - const { category: themeCategory } = themeMeta - - const ref = useRef(null) - useCustomScroll(ref, { - scrollbars: { autoHide: autoHide ? 'scroll' : 'never' }, - themeCategory, - }) - - return ( - - {showShadow && ( - - )} - - - - {/* @ts-ignore */} - - {children} - {/* @ts-ignore */} - - - - {showShadow && ( - - )} - - ) -} - -export default memo(HorizontalScroller) diff --git a/src/widgets/CustomScroller/VerticalScroller.tsx b/src/widgets/CustomScroller/VerticalScroller.tsx index 95b339fec..3e298f440 100755 --- a/src/widgets/CustomScroller/VerticalScroller.tsx +++ b/src/widgets/CustomScroller/VerticalScroller.tsx @@ -4,14 +4,13 @@ * */ -import { FC, useState, useRef, useCallback, memo } from 'react' +import { FC, useState, Fragment, useCallback, memo } from 'react' // NOTE: do not use ViewportTracker here, it cause crash import { Waypoint } from 'react-waypoint' +import { OverlayScrollbarsComponent } from 'overlayscrollbars-react' import SIZE from '@/constant/size' -import { debounce } from '@/helper' -import useCustomScroll from '@/hooks/useCustomScroll' import useTheme from '@/hooks/useTheme' // import ViewportTracker from '@/widgets/ViewportTracker' @@ -20,8 +19,8 @@ import type { TProps as TScrollProps } from '.' import { Wrapper, + ViewHolder, // - ScrollWrapper, TopShadowBar, BottomShadowBar, } from './styles/vertical_scroller' @@ -46,7 +45,7 @@ const VerticalScroller: FC = ({ onScrollDirectionChange, instanceKey = null, }) => { - const [showTopShadow, setShowTopShadow] = useState(false) + const [showTopShadow, setShowTopShadow] = useState(true) const [showBottomShadow, setShowBottomShadow] = useState(true) // record last y position after scroll @@ -78,53 +77,15 @@ const VerticalScroller: FC = ({ const { _meta: themeMeta } = themeMap const { category: themeCategory } = themeMeta - const ref = useRef(null) - const scrollInstance = useCustomScroll(ref, { - instanceKey, - scrollbars: { autoHide: autoHide ? 'scroll' : 'never' }, - themeCategory, - callbacks: { - onScroll: debounce(() => { - const position = scrollInstance?.scroll().position - if (position) { - const currentY = position.y - - currentY > lastYPosition - ? onScrollDirectionChange?.('up') - : onScrollDirectionChange?.('down') - } - }, 100), - onScrollStart: () => { - const position = scrollInstance?.scroll().position - if (position) { - const currentY = position.y - setLastYPosition(currentY) - - currentY > lastYPosition - ? onScrollDirectionChange?.('up') - : onScrollDirectionChange?.('down') - } - }, - onScrollStop: () => { - const position = scrollInstance?.scroll().position - if (position) { - const currentY = position.y - currentY > lastYPosition - ? onScrollDirectionChange?.('up') - : onScrollDirectionChange?.('down') - } - }, - }, - }) - + // return ( - + {showShadow && ( = ({ /> )} - - {/* @ts-ignore */} + + -
{children}
- {/* @ts-ignore */} + {children} + -
+ {showShadow && ( = ({ withBorder={withBorder} /> )} -
+ ) } diff --git a/src/widgets/CustomScroller/index.tsx b/src/widgets/CustomScroller/index.tsx index 4e67f3505..a013a8aed 100755 --- a/src/widgets/CustomScroller/index.tsx +++ b/src/widgets/CustomScroller/index.tsx @@ -3,11 +3,11 @@ import { FC, ReactNode, memo } from 'react' import type { TSizeSML } from '@/spec' import type { TDirection, TScrollDirection } from './spec' -import HorizontalScroller from './HorizontalScroller' +// import HorizontalScroller from './HorizontalScroller' import VerticalScroller from './VerticalScroller' export type TProps = { - direction: TDirection + direction?: TDirection children: ReactNode height?: string innerHeight?: string @@ -29,16 +29,8 @@ export type TProps = { onScrollDirectionChange?: (dir: TScrollDirection) => void } -const CustomScroller: FC = ({ - children, - direction = 'vertical', - ...restProps -}) => { - return direction === 'vertical' ? ( - {children} - ) : ( - {children} - ) +const CustomScroller: FC = ({ children, direction = 'vertical', ...restProps }) => { + return {children} } export default memo(CustomScroller) diff --git a/src/widgets/CustomScroller/styles/index.ts b/src/widgets/CustomScroller/styles/index.ts index d039e928c..1efe50ed4 100755 --- a/src/widgets/CustomScroller/styles/index.ts +++ b/src/widgets/CustomScroller/styles/index.ts @@ -5,8 +5,8 @@ import type { TActive } from '@/spec' type TBox = { width: string; height: string } export const WrapperBase = styled.div` - width: ${({ width }) => width}; - height: ${({ height }) => height}; + /* width: ${({ width }) => width}; + height: ${({ height }) => height}; */ ` export const ScrollWrapperBase = styled.div` width: 100%; diff --git a/src/widgets/CustomScroller/styles/vertical_scroller.ts b/src/widgets/CustomScroller/styles/vertical_scroller.ts index 2e6480571..8b6897486 100755 --- a/src/widgets/CustomScroller/styles/vertical_scroller.ts +++ b/src/widgets/CustomScroller/styles/vertical_scroller.ts @@ -5,6 +5,11 @@ import styled from 'styled-components' import { WrapperBase, ScrollWrapperBase, ShadowBarBase } from '.' import { getShadowBackground, getShadowSize, getScrollbarThin } from './metrics' +export const ViewHolder = styled.div` + width: 100%; + height: 1px; +` + type TBar = { width?: string height: string @@ -13,8 +18,10 @@ type TBar = { withBorder?: boolean $shadowSize: string } -export const Wrapper = styled(WrapperBase)` +// export const Wrapper = styled(WrapperBase)` +export const Wrapper = styled.div` position: relative; + border: 1px solid blue; .os-host:not(:hover) { visibility: ${({ $showOnHover }) => ($showOnHover ? 'hidden' : 'inherit')}; diff --git a/src/widgets/FeedsBar/List.tsx b/src/widgets/FeedsBar/List.tsx deleted file mode 100755 index 5ca97c374..000000000 --- a/src/widgets/FeedsBar/List.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * List - * - */ - -import { FC, memo } from 'react' - -import { ICON_CMD } from '@/config' -import { buildLog } from '@/logger' - -import CustomScroller from '@/widgets/CustomScroller' -import { SpaceGrow } from '@/widgets/Common' - -import { mockList } from './mock' - -import { ListItemWrapper, Header, Icon, InfoIcon, Timestamp, Title } from './styles/list' - -/* eslint-disable-next-line */ -const log = buildLog('w:FeedsBar:index') - -const List: FC = () => { - // list header(with lable) - 40px - // source select - 75px - const listHeadHeight = '105px' - const items = mockList() - - return ( - - {items.map((item) => ( - -
- - {item.source} - - - {item.createdAt} -
- {item.title} -
- ))} -
- ) -} - -export default memo(List) diff --git a/src/widgets/FeedsBar/SourceSelector.tsx b/src/widgets/FeedsBar/SourceSelector.tsx deleted file mode 100755 index 4eac607b2..000000000 --- a/src/widgets/FeedsBar/SourceSelector.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * SourceSelector - * - */ - -import { FC, memo } from 'react' - -import { buildLog } from '@/logger' -import CustomScroller from '@/widgets/CustomScroller' -import { Wrapper, Icon, Block, Title } from './styles/source_selector' - -import { mockSource } from './mock' - -/* eslint-disable-next-line */ -const log = buildLog('w:SourceSelector:index') - -const SourceSelector: FC = () => { - const items = mockSource() - - return ( - - - {items.map((item) => ( - - - {item.title} - - ))} - - - ) -} - -export default memo(SourceSelector) diff --git a/src/widgets/FeedsBar/index.tsx b/src/widgets/FeedsBar/index.tsx deleted file mode 100755 index 1434fa97e..000000000 --- a/src/widgets/FeedsBar/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * FeedsBar - * - */ - -import { FC, memo } from 'react' - -import { ICON_CMD } from '@/config' -import { buildLog } from '@/logger' - -import { SpaceGrow } from '@/widgets/Common' -import SourceSelector from './SourceSelector' -import List from './List' - -import { Wrapper, Header, FunctionIcon, Title } from './styles' - -/* eslint-disable-next-line */ -const log = buildLog('w:FeedsBar:index') - -type TProps = { - title: string -} - -const FeedsBar: FC = ({ title }) => { - return ( - -
- {title} - - -
- - -
- ) -} - -export default memo(FeedsBar) diff --git a/src/widgets/FeedsBar/mock.ts b/src/widgets/FeedsBar/mock.ts deleted file mode 100755 index 0cc8663d7..000000000 --- a/src/widgets/FeedsBar/mock.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { ICON_CMD } from '@/config' - -export const mockList = () => { - return [ - { - id: '0', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - source: 'hackernews', - createdAt: '3天前', - title: 'Thank HN: You helped me get a new job', - }, - { - id: '1', - icon: `${ICON_CMD}/hot/techcrunch.png`, - source: 'techcrunch', - createdAt: '3天前', - title: - 'atch Critical Cryptographic Vulnerability in Microsoft Windows [pdf]', - }, - { - id: '2', - icon: `${ICON_CMD}/hot/infoq.jpg`, - source: 'infoQ 中文站', - createdAt: '2天前', - title: '苹果走钢丝:为iPhone隐私大战FBI,还是屈服于特朗普?', - }, - { - id: '3', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - source: 'hackernews', - createdAt: '3天前', - title: 'Thank HN: You helped me get a new job', - }, - { - id: '4', - icon: `${ICON_CMD}/hot/techcrunch.png`, - source: 'techcrunch', - createdAt: '3天前', - title: - 'atch Critical Cryptographic Vulnerability in Microsoft Windows [pdf]', - }, - { - id: '5', - icon: `${ICON_CMD}/hot/infoq.jpg`, - source: 'infoQ 中文站', - createdAt: '2天前', - title: '苹果走钢丝:为iPhone隐私大战FBI,还是屈服于特朗普?', - }, - { - id: '6', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - source: 'hackernews', - createdAt: '3天前', - title: 'Thank HN: You helped me get a new job', - }, - { - id: '7', - icon: `${ICON_CMD}/hot/techcrunch.png`, - source: 'techcrunch', - createdAt: '3天前', - title: - 'atch Critical Cryptographic Vulnerability in Microsoft Windows [pdf]', - }, - { - id: '8', - icon: `${ICON_CMD}/hot/infoq.jpg`, - source: 'infoQ 中文站', - createdAt: '2天前', - title: '苹果走钢丝:为iPhone隐私大战FBI,还是屈服于特朗普?', - }, - { - id: '9', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - source: 'hackernews', - createdAt: '3天前', - title: 'Thank HN: You helped me get a new job', - }, - { - id: '10', - icon: `${ICON_CMD}/hot/techcrunch.png`, - source: 'techcrunch', - createdAt: '3天前', - title: - 'atch Critical Cryptographic Vulnerability in Microsoft Windows [pdf]', - }, - { - id: '11', - icon: `${ICON_CMD}/hot/infoq.jpg`, - source: 'infoQ 中文站', - createdAt: '2天前', - title: '苹果走钢丝:为iPhone隐私大战FBI,还是屈服于特朗普?', - }, - { - id: '12', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - source: 'hackernews', - createdAt: '3天前', - title: 'Thank HN: You helped me get a new job', - }, - { - id: '13', - icon: `${ICON_CMD}/hot/techcrunch.png`, - source: 'techcrunch', - createdAt: '3天前', - title: - 'atch Critical Cryptographic Vulnerability in Microsoft Windows [pdf]', - }, - { - id: '14', - icon: `${ICON_CMD}/hot/infoq.jpg`, - source: 'infoQ 中文站', - createdAt: '2天前', - title: 'Footer', - }, - ] -} - -export const mockSource = () => { - return [ - { - id: '0', - icon: `${ICON_CMD}/hot/techcrunch.png`, - title: 'techcrunch', - }, - { - id: '1', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - title: 'hackernews', - }, - { - id: '2', - icon: `${ICON_CMD}/hot/infoq.jpg`, - title: 'infoQ', - }, - { - id: '3', - icon: `${ICON_CMD}/hot/techcrunch.png`, - title: 'techcrunch', - }, - { - id: '4', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - title: 'hackernews', - }, - { - id: '5', - icon: `${ICON_CMD}/hot/infoq.jpg`, - title: 'infoQ', - }, - { - id: '21', - icon: `${ICON_CMD}/hot/infoq.jpg`, - title: 'infoQ', - }, - { - id: '31', - icon: `${ICON_CMD}/hot/techcrunch.png`, - title: 'techcrunch', - }, - { - id: '41', - icon: `${ICON_CMD}/hot/hackernews.jpeg`, - title: 'hackernews', - }, - { - id: '51', - icon: `${ICON_CMD}/hot/infoq.jpg`, - title: 'infoQ', - }, - ] -} diff --git a/src/widgets/FeedsBar/styles/index.ts b/src/widgets/FeedsBar/styles/index.ts deleted file mode 100755 index 731998c79..000000000 --- a/src/widgets/FeedsBar/styles/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -const bgColor = '#02303e' - -export const Wrapper = styled.div` - width: 320px; - color: ${theme('article.digest')}; - /* background: #02303e; */ - /* height: 90vh; */ - height: 100%; - margin-right: 15px; - flex-shrink: 0; - border: 1px solid; - border-color: ${bgColor}; - background-color: ${bgColor}; - border-radius: 3px; - overflow-y: hidden; -` -export const Header = styled.div` - position: relative; - ${css.row('align-center')}; - padding: 6px 8px 5px 0; - color: ${theme('article.digest')}; -` -export const FunctionIcon = styled(Img)` - ${css.size(18)}; - fill: ${theme('article.digest')}; - &:hover { - fill: ${theme('article.title')}; - cursor: pointer; - } -` -export const Title = styled.div` - position: absolute; - top: -2px; - left: 0; - background: #0d4152; - padding: 2px 10px; - color: #92a4a5; - border-top-right-radius: 5px; - border-bottom-right-radius: 5px; - - ${Wrapper}:hover & { - font-weight: bold; - } - transition: all 0.2s; -` -// color: #cecece; -// padding: 8px 10px; -// color: #cecece; -// background: #006f74; diff --git a/src/widgets/FeedsBar/styles/list.ts b/src/widgets/FeedsBar/styles/list.ts deleted file mode 100755 index 21da9bc1e..000000000 --- a/src/widgets/FeedsBar/styles/list.ts +++ /dev/null @@ -1,51 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -export const ListItemWrapper = styled.div` - width: 100%; - color: ${theme('article.digest')}; - border-bottom: 1px solid; - border-bottom-color: #034256; - padding: 10px; - - &:last-child { - border-bottom: none; - } -` -export const Header = styled.div` - ${css.row('align-center')}; - margin-bottom: 4px; - color: ${theme('article.digest')}; -` -export const Icon = styled(Img)` - ${css.circle(13)}; - margin-right: 6px; -` -export const InfoIcon = styled(Img)` - ${css.circle(13)}; - fill: ${theme('article.digest')}; - margin-left: 5px; - opacity: 0; - - ${Header}:hover & { - fill: ${theme('article.title')}; - cursor: pointer; - opacity: 1; - } - transition: all 0.2s; -` -export const Timestamp = styled.div` - ${css.row()}; - color: ${theme('article.digest')}; - font-size: 12px; -` -export const Title = styled.div` - color: ${theme('article.title')}; - font-size: 14px; - &:hover { - cursor: pointer; - text-decoration: underline; - } -` diff --git a/src/widgets/FeedsBar/styles/source_selector.ts b/src/widgets/FeedsBar/styles/source_selector.ts deleted file mode 100755 index 74d6898e7..000000000 --- a/src/widgets/FeedsBar/styles/source_selector.ts +++ /dev/null @@ -1,38 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import css, { theme } from '@/css' - -export const Wrapper = styled.div` - position: relative; - width: 100%; - height: 75px; - color: ${theme('article.digest')}; - background: #022935; - border: 1px solid; - border-color: #013648; - padding-top: 2x; -` -export const Header = styled.div` - ${css.row()}; - color: ${theme('article.digest')}; -` -// padding: 10px 2px; -export const Block = styled.div` - ${css.column('align-both')}; - margin-right: 5px; - - &:hover { - cursor: pointer; - background: #05303e; - } -` -export const Icon = styled(Img)` - ${css.circle(30)}; -` -export const Title = styled.div` - ${css.cutRest('50px')}; - text-align: center; - padding-left: 5px; - color: ${theme('article.digest')}; -` diff --git a/src/widgets/FeedsBar/tests/index.test.ts b/src/widgets/FeedsBar/tests/index.test.ts deleted file mode 100755 index 32a8b125b..000000000 --- a/src/widgets/FeedsBar/tests/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react' -// import { shallow } from 'enzyme' - -// import FeedsBar from '..' - -describe('TODO ', () => { - it('Expect to have unit tests specified', () => { - expect(true).toEqual(true) - }) -}) diff --git a/src/widgets/GlobalLayout/Addon.tsx b/src/widgets/GlobalLayout/Addon.tsx index e68014b8d..7e94dd0c9 100644 --- a/src/widgets/GlobalLayout/Addon.tsx +++ b/src/widgets/GlobalLayout/Addon.tsx @@ -6,10 +6,10 @@ import { observer } from 'mobx-react-lite' import { Toaster } from 'sonner' import useShortcut from '@/hooks/useShortcut' -import useMetric from '@/hooks/useMetric' import Drawer from '@/containers/tool/Drawer' import ErrorBox from '@/containers/tool/ErrorBox' +import UserListModal from '@/widgets/UserListModal' // import { Drawer } from './dynamic' @@ -17,14 +17,14 @@ const Addon: FC = () => { // const { isMobile } = useMobileDetect() useShortcut('Control+P', () => console.log('# Ctrl P pressed')) - const metric = useMetric() return ( {/* @ts-ignore */} {/* {!isMobile && } */} {/* @ts-ignore */} - + + {/* @ts-ignore */} diff --git a/src/widgets/Modal/styles/index.ts b/src/widgets/Modal/styles/index.ts index 2a12fda48..768902ce6 100755 --- a/src/widgets/Modal/styles/index.ts +++ b/src/widgets/Modal/styles/index.ts @@ -35,10 +35,8 @@ export const Wrapper = styled.div` min-height: 320px; max-height: 65vh; box-shadow: ${theme('modal.shadow')}; - padding-top: 25px; - /* border: 1px solid; */ - /* border-top: 2px solid; */ - border-color: ${({ mode }) => theme('modal.border')}; + border: 1px solid; + border-color: ${theme('popover.borderColor')}; animation: ${animate.jump} 0.3s linear; margin-left: ${({ offsetLeft }) => offsetLeft}; diff --git a/src/widgets/ThemePalette/ScrollBarStyle.ts b/src/widgets/ThemePalette/ScrollBarStyle.ts index 98690cd55..b68baa204 100644 --- a/src/widgets/ThemePalette/ScrollBarStyle.ts +++ b/src/widgets/ThemePalette/ScrollBarStyle.ts @@ -1,5 +1,6 @@ import { createGlobalStyle } from 'styled-components' +import { theme } from '@/css' /*! * OverlayScrollbars * https://github.com/KingSora/OverlayScrollbars @@ -18,559 +19,682 @@ OVERLAY SCROLLBARS CORE: */ const ScrollBarStyle = createGlobalStyle` - /*! - * OverlayScrollbars - * Version: 2.0.1 - * - * Copyright (c) Rene Haas | KingSora. - * https://github.com/KingSora - * - * Released under the MIT license. - */ - .os-size-observer, - .os-size-observer-listener { - direction: inherit; - pointer-events: none; - overflow: hidden; - visibility: hidden; - box-sizing: border-box; - } - - .os-size-observer, - .os-size-observer-listener, - .os-size-observer-listener-item, - .os-size-observer-listener-item-final { - writing-mode: horizontal-tb; - position: absolute; - left: 0; - top: 0; - } - - .os-size-observer { - z-index: -1; - contain: strict; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - padding: inherit; - border: inherit; - box-sizing: inherit; - margin: -133px; - top: 0; - right: 0; - bottom: 0; - left: 0; - transform: scale(0.1); - } - .os-size-observer::before { - content: ""; - flex: none; - box-sizing: inherit; - padding: 10px; - width: 10px; - height: 10px; - } - - .os-size-observer-appear { - animation: os-size-observer-appear-animation 1ms forwards; - } - - .os-size-observer-listener { - box-sizing: border-box; - position: relative; - flex: auto; - padding: inherit; - border: inherit; - margin: -133px; - transform: scale(10); - } - .os-size-observer-listener.ltr { - margin-right: -266px; - margin-left: 0; - } - .os-size-observer-listener.rtl { - margin-left: -266px; - margin-right: 0; - } - .os-size-observer-listener:empty::before { - content: ""; - width: 100%; - height: 100%; - } - .os-size-observer-listener:empty::before, .os-size-observer-listener > .os-size-observer-listener-item { - display: block; - position: relative; - padding: inherit; - border: inherit; - box-sizing: content-box; - flex: auto; - } - - .os-size-observer-listener-scroll { - box-sizing: border-box; - display: flex; - } - - .os-size-observer-listener-item { - right: 0; - bottom: 0; - overflow: hidden; - direction: ltr; - flex: none; - } - - .os-size-observer-listener-item-final { - transition: none; - } - - @keyframes os-size-observer-appear-animation { - from { - cursor: auto; - } - to { - cursor: none; - } - } - .os-trinsic-observer { - flex: none; - box-sizing: border-box; - position: relative; - max-width: 0px; - max-height: 1px; - padding: 0; - margin: 0; - border: none; - overflow: hidden; - z-index: -1; - height: 0; - top: calc(100% + 1px); - contain: strict; - } - .os-trinsic-observer:not(:empty) { - height: calc(100% + 1px); - top: -1px; - } - .os-trinsic-observer:not(:empty) > .os-size-observer { - width: 1000%; - height: 1000%; - min-height: 1px; - min-width: 1px; - } - - /** - * environment setup - */ - .os-environment { - --os-custom-prop: -1; - position: fixed; - opacity: 0; - visibility: hidden; - overflow: scroll; - height: 200px; - width: 200px; - z-index: var(--os-custom-prop); - } - .os-environment div { - width: 200%; - height: 200%; - margin: 10px 0; - } - .os-environment.os-environment-flexbox-glue { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - height: auto; - width: auto; - min-height: 200px; - min-width: 200px; - } - .os-environment.os-environment-flexbox-glue div { - flex: auto; - width: auto; - height: auto; - max-height: 100%; - max-width: 100%; - margin: 0; - } - .os-environment.os-environment-flexbox-glue-max { - max-height: 200px; - } - .os-environment.os-environment-flexbox-glue-max div { - overflow: visible; - } - .os-environment.os-environment-flexbox-glue-max div::before { - content: ""; - display: block; - height: 999px; - width: 999px; - } - - /** - * hide native scrollbars - */ - .os-environment, - .os-viewport { - -ms-overflow-style: scrollbar !important; - } - - [data-overlayscrollbars-initialize], - [data-overlayscrollbars~=scrollbarHidden], - .os-viewport-scrollbar-hidden.os-environment, - .os-viewport-scrollbar-hidden.os-viewport { - scrollbar-width: none !important; - } - - [data-overlayscrollbars-initialize]::-webkit-scrollbar, - [data-overlayscrollbars-initialize]::-webkit-scrollbar-corner, - [data-overlayscrollbars~=scrollbarHidden]::-webkit-scrollbar, - [data-overlayscrollbars~=scrollbarHidden]::-webkit-scrollbar-corner, - .os-viewport-scrollbar-hidden.os-environment::-webkit-scrollbar, - .os-viewport-scrollbar-hidden.os-environment::-webkit-scrollbar-corner, - .os-viewport-scrollbar-hidden.os-viewport::-webkit-scrollbar, - .os-viewport-scrollbar-hidden.os-viewport::-webkit-scrollbar-corner { - -webkit-appearance: none !important; - appearance: none !important; - display: none !important; - width: 0 !important; - height: 0 !important; - } - - /** - * elements wont suddenly crop after initialization is done - */ - [data-overlayscrollbars-initialize] { - overflow: auto; - } - - /** - * applied to body - */ - html[data-overlayscrollbars], - html.os-viewport-scrollbar-hidden, - html.os-viewport-scrollbar-hidden > body { - box-sizing: border-box; - margin: 0; - width: 100%; - height: 100%; - } - - html[data-overlayscrollbars] > body { - overflow: visible; - } - - /** - * structure setup - */ - [data-overlayscrollbars~=host], - .os-padding { - position: relative; - } - - [data-overlayscrollbars~=host], - .os-padding { - display: flex; - flex-direction: row !important; - flex-wrap: nowrap !important; - } - - .os-padding, - .os-viewport { - box-sizing: inherit; - position: relative; - flex: auto !important; - height: auto; - width: 100%; - padding: 0; - margin: 0; - border: none; - z-index: 0; - } - - .os-viewport { - --os-vaw: 0; - --os-vah: 0; - } - .os-viewport.os-viewport-arrange::before { - content: ""; - position: absolute; - pointer-events: none; - z-index: -1; - min-width: 1px; - min-height: 1px; - width: var(--os-vaw); - height: var(--os-vah); - } - - [data-overlayscrollbars~=host], - [data-overlayscrollbars~=viewport] { - overflow: hidden; - } - - [data-overlayscrollbars~=overflowVisible] { - overflow: visible; - } - - [data-overlayscrollbars-overflow-x=hidden] { - overflow-x: hidden; - } - - [data-overlayscrollbars-overflow-x=scroll] { - overflow-x: scroll; - } - - [data-overlayscrollbars-overflow-x=hidden] { - overflow-y: hidden; - } - - [data-overlayscrollbars-overflow-y=scroll] { - overflow-y: scroll; - } - - .os-padding, - .os-viewport { - overflow: hidden; - } - - .os-overflow-visible { - overflow: visible; - } - - .os-content { - box-sizing: inherit; - } - - /** - * optional & experimental grid mode - */ - [data-overlayscrollbars-grid], - [data-overlayscrollbars-grid] .os-padding { - display: grid; - grid-template: 1fr/1fr; - } - - [data-overlayscrollbars-grid] > .os-padding, - [data-overlayscrollbars-grid] > .os-viewport, - [data-overlayscrollbars-grid] > .os-padding > .os-viewport { - height: auto !important; - width: auto !important; - } - - .os-scrollbar { - contain: strict; - transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s; - pointer-events: none; - position: absolute; - opacity: 0; - visibility: hidden; - } - - body > .os-scrollbar { - position: fixed; - z-index: 99999; - } - - .os-scrollbar-transitionless { - transition: none; - } - - .os-scrollbar-track { - position: relative; - direction: ltr !important; - padding: 0 !important; - border: none !important; - } - - .os-scrollbar-handle { - position: absolute; - } - - .os-scrollbar-track, - .os-scrollbar-handle { - pointer-events: none; - width: 100%; - height: 100%; - } - - .os-scrollbar.os-scrollbar-track-interactive .os-scrollbar-track, - .os-scrollbar.os-scrollbar-handle-interactive .os-scrollbar-handle { - pointer-events: auto; - touch-action: none; - } - - .os-scrollbar-horizontal { - bottom: 0; - left: 0; - } - - .os-scrollbar-vertical { - top: 0; - right: 0; - } - - .os-scrollbar-rtl.os-scrollbar-horizontal { - right: 0; - } - - .os-scrollbar-rtl.os-scrollbar-vertical { - right: auto; - left: 0; - } - - .os-scrollbar-visible, - .os-scrollbar-interaction.os-scrollbar-visible { - opacity: 1; - visibility: visible; - } - - .os-scrollbar-auto-hidden { - opacity: 0; - visibility: hidden; - } - - .os-scrollbar-unusable, - .os-scrollbar-unusable *, - .os-scrollbar-wheel, - .os-scrollbar-wheel * { - pointer-events: none !important; - } - - .os-scrollbar-unusable .os-scrollbar-handle { - opacity: 0 !important; - } - - .os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless, - .os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless.os-scrollbar-rtl { - left: 0; - right: 0; - } - - .os-scrollbar.os-scrollbar-vertical.os-scrollbar-cornerless, - .os-scrollbar.os-scrollbar-vertical.os-scrollbar-cornerless.os-scrollbar-rtl { - top: 0; - bottom: 0; - } - - /* NONE THEME: */ - [data-overlayscrollbars~=updating] > .os-scrollbar, - .os-theme-none.os-scrollbar { - display: none !important; - } - - /* DARK & LIGHT THEME: */ - .os-theme-dark.os-scrollbar-horizontal, - .os-theme-light.os-scrollbar-horizontal { - right: 10px; - height: 10px; - } - - .os-theme-dark.os-scrollbar-vertical, - .os-theme-light.os-scrollbar-vertical { - bottom: 10px; - width: 10px; - } - - .os-theme-dark.os-scrollbar-rtl.os-scrollbar-horizontal, - .os-theme-light.os-scrollbar-rtl.os-scrollbar-horizontal { - left: 10px; - right: 0; - } - - .os-theme-dark.os-scrollbar, - .os-theme-light.os-scrollbar { - padding: 2px; - box-sizing: border-box; - background: transparent; - } - - .os-theme-dark.os-scrollbar-unusable, - .os-theme-light.os-scrollbar-unusable { - background: transparent; - } - - .os-theme-dark.os-scrollbar > .os-scrollbar-track, - .os-theme-light.os-scrollbar > .os-scrollbar-track { - background: transparent; - } - - .os-theme-dark.os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle, - .os-theme-light.os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle { - min-width: 30px; - } - - .os-theme-dark.os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle, - .os-theme-light.os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle { - min-height: 30px; - } - - .os-theme-dark.os-scrollbar-transition > .os-scrollbar-track > .os-scrollbar-handle, - .os-theme-light.os-scrollbar-transition > .os-scrollbar-track > .os-scrollbar-handle { - transition: background-color 0.3s; - } - - .os-theme-dark.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, - .os-theme-light.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, - .os-theme-dark.os-scrollbar > .os-scrollbar-track, - .os-theme-light.os-scrollbar > .os-scrollbar-track { - border-radius: 10px; - } - - .os-theme-dark.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - background: rgb(148 148 148 / 55%); - } - - .os-theme-light.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(255, 255, 255, 0.4); - } - - .os-theme-dark.os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(0, 0, 0, 0.55); - } - - .os-theme-light.os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(255, 255, 255, 0.55); - } - - .os-theme-dark.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { - background: rgba(0, 0, 0, 0.7); - } - - .os-theme-light.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { - background: rgba(255, 255, 255, 0.7); - } - - .os-theme-dark.os-scrollbar-horizontal .os-scrollbar-handle:before, - .os-theme-dark.os-scrollbar-vertical .os-scrollbar-handle:before, - .os-theme-light.os-scrollbar-horizontal .os-scrollbar-handle:before, - .os-theme-light.os-scrollbar-vertical .os-scrollbar-handle:before { - content: ""; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: block; - } - - .os-theme-dark.os-host-scrollbar-hidden > .os-scrollbar-handle:before { - display: none; - } - - .os-theme-dark.os-scrollbar-horizontal .os-scrollbar-handle:before, - .os-theme-light.os-scrollbar-horizontal .os-scrollbar-handle:before { - top: -6px; - bottom: -2px; - } +/*! + * OverlayScrollbars + * Version: 2.4.5 + * + * Copyright (c) Rene Haas | KingSora. + * https://github.com/KingSora + * + * Released under the MIT license. + */ +.os-size-observer, +.os-size-observer-listener { + scroll-behavior: auto !important; + direction: inherit; + pointer-events: none; + overflow: hidden; + visibility: hidden; + box-sizing: border-box; +} + +.os-size-observer, +.os-size-observer-listener, +.os-size-observer-listener-item, +.os-size-observer-listener-item-final { + writing-mode: horizontal-tb; + position: absolute; + left: 0; + top: 0; +} + +.os-size-observer { + z-index: -1; + contain: strict; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + padding: inherit; + border: inherit; + box-sizing: inherit; + margin: -133px; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: scale(0.1); +} +.os-size-observer::before { + content: ""; + flex: none; + box-sizing: inherit; + padding: 10px; + width: 10px; + height: 10px; +} + +.os-size-observer-appear { + animation: os-size-observer-appear-animation 1ms forwards; +} + +.os-size-observer-listener { + box-sizing: border-box; + position: relative; + flex: auto; + padding: inherit; + border: inherit; + margin: -133px; + transform: scale(10); +} +.os-size-observer-listener.ltr { + margin-right: -266px; + margin-left: 0; +} +.os-size-observer-listener.rtl { + margin-left: -266px; + margin-right: 0; +} +.os-size-observer-listener:empty::before { + content: ""; + width: 100%; + height: 100%; +} +.os-size-observer-listener:empty::before, .os-size-observer-listener > .os-size-observer-listener-item { + display: block; + position: relative; + padding: inherit; + border: inherit; + box-sizing: content-box; + flex: auto; +} + +.os-size-observer-listener-scroll { + box-sizing: border-box; + display: flex; +} + +.os-size-observer-listener-item { + right: 0; + bottom: 0; + overflow: hidden; + direction: ltr; + flex: none; +} + +.os-size-observer-listener-item-final { + transition: none; +} + +@keyframes os-size-observer-appear-animation { + from { + cursor: auto; + } + to { + cursor: none; + } +} +.os-trinsic-observer { + flex: none; + box-sizing: border-box; + position: relative; + max-width: 0px; + max-height: 1px; + padding: 0; + margin: 0; + border: none; + overflow: hidden; + z-index: -1; + height: 0; + top: calc(100% + 1px); + contain: strict; +} +.os-trinsic-observer:not(:empty) { + height: calc(100% + 1px); + top: -1px; +} +.os-trinsic-observer:not(:empty) > .os-size-observer { + width: 1000%; + height: 1000%; + min-height: 1px; + min-width: 1px; +} + +/** + * environment setup + */ +.os-environment { + scroll-behavior: auto !important; + --os-custom-prop: -1; + position: fixed; + opacity: 0; + visibility: hidden; + overflow: scroll; + height: 200px; + width: 200px; + z-index: var(--os-custom-prop); +} +.os-environment div { + width: 200%; + height: 200%; + margin: 10px 0; +} +.os-environment.os-environment-flexbox-glue { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + height: auto; + width: auto; + min-height: 200px; + min-width: 200px; +} +.os-environment.os-environment-flexbox-glue div { + flex: auto; + width: auto; + height: auto; + max-height: 100%; + max-width: 100%; + margin: 0; +} +.os-environment.os-environment-flexbox-glue-max { + max-height: 200px; +} +.os-environment.os-environment-flexbox-glue-max div { + overflow: visible; +} +.os-environment.os-environment-flexbox-glue-max div::before { + content: ""; + display: block; + height: 999px; + width: 999px; +} + +/** + * hide native scrollbars + */ +.os-environment, +[data-overlayscrollbars-viewport] { + -ms-overflow-style: scrollbar !important; +} + +[data-overlayscrollbars-initialize], +[data-overlayscrollbars~=scrollbarHidden], +[data-overlayscrollbars-viewport~=scrollbarHidden], +.os-scrollbar-hidden.os-environment { + scrollbar-width: none !important; +} + +[data-overlayscrollbars-initialize]::-webkit-scrollbar, +[data-overlayscrollbars-initialize]::-webkit-scrollbar-corner, +[data-overlayscrollbars~=scrollbarHidden]::-webkit-scrollbar, +[data-overlayscrollbars~=scrollbarHidden]::-webkit-scrollbar-corner, +[data-overlayscrollbars-viewport~=scrollbarHidden]::-webkit-scrollbar, +[data-overlayscrollbars-viewport~=scrollbarHidden]::-webkit-scrollbar-corner, +.os-scrollbar-hidden.os-environment::-webkit-scrollbar, +.os-scrollbar-hidden.os-environment::-webkit-scrollbar-corner { + -webkit-appearance: none !important; + appearance: none !important; + display: none !important; + width: 0 !important; + height: 0 !important; +} + +/** + * elements wont suddenly crop after initialization is done + */ +[data-overlayscrollbars-initialize]:not([data-overlayscrollbars]):not(html):not(body) { + overflow: auto; +} - .os-theme-dark.os-scrollbar-vertical .os-scrollbar-handle:before, - .os-theme-light.os-scrollbar-vertical .os-scrollbar-handle:before { - left: -6px; - right: -2px; - } +/** + * applied to body + */ +html[data-overlayscrollbars], +html.os-scrollbar-hidden, +html.os-scrollbar-hidden > body { + box-sizing: border-box; + margin: 0; + width: 100%; + height: 100%; +} + +html[data-overlayscrollbars] > body { + overflow: visible; +} + +/** + * structure setup + */ +[data-overlayscrollbars~=host], +[data-overlayscrollbars-padding] { + display: flex; + align-items: stretch !important; + flex-direction: row !important; + flex-wrap: nowrap !important; +} + +[data-overlayscrollbars-padding], +[data-overlayscrollbars-viewport] { + box-sizing: inherit; + position: relative; + flex: auto !important; + height: auto; + width: 100%; + min-width: 0; + padding: 0; + margin: 0; + border: none; + z-index: 0; +} + +[data-overlayscrollbars-viewport] { + --os-vaw: 0; + --os-vah: 0; +} +[data-overlayscrollbars-viewport][data-overlayscrollbars-viewport~=arrange]::before { + content: ""; + position: absolute; + pointer-events: none; + z-index: -1; + min-width: 1px; + min-height: 1px; + width: var(--os-vaw); + height: var(--os-vah); +} + +[data-overlayscrollbars-padding], +[data-overlayscrollbars-viewport] { + overflow: hidden; +} + +[data-overlayscrollbars~=host], +[data-overlayscrollbars~=viewport] { + position: relative; + overflow: hidden; +} + +[data-overlayscrollbars~=overflowVisible], +[data-overlayscrollbars-padding~=overflowVisible], +[data-overlayscrollbars-viewport~=overflowVisible] { + overflow: visible; +} + +[data-overlayscrollbars-overflow-x=hidden] { + overflow-x: hidden; +} + +[data-overlayscrollbars-overflow-x=scroll] { + overflow-x: scroll; +} + +[data-overlayscrollbars-overflow-x=hidden] { + overflow-y: hidden; +} + +[data-overlayscrollbars-overflow-y=scroll] { + overflow-y: scroll; +} + +[data-overlayscrollbars~=scrollbarPressed], +[data-overlayscrollbars~=scrollbarPressed] [data-overlayscrollbars-viewport] { + scroll-behavior: auto !important; +} + +[data-overlayscrollbars-content] { + box-sizing: inherit; +} + +/** + * Display contents to bridge any flickering during deferred initialization. + */ +[data-overlayscrollbars-contents]:not([data-overlayscrollbars-padding]):not([data-overlayscrollbars-viewport]):not([data-overlayscrollbars-content]) { + display: contents; +} - .os-theme-dark.os-scrollbar-rtl.os-scrollbar-vertical .os-scrollbar-handle:before, - .os-theme-light.os-scrollbar-rtl.os-scrollbar-vertical .os-scrollbar-handle:before { - right: -6px; - left: -2px; - } +/** + * optional & experimental grid mode + */ +[data-overlayscrollbars-grid], +[data-overlayscrollbars-grid] [data-overlayscrollbars-padding] { + display: grid; + grid-template: 1fr/1fr; +} + +[data-overlayscrollbars-grid] > [data-overlayscrollbars-padding], +[data-overlayscrollbars-grid] > [data-overlayscrollbars-viewport], +[data-overlayscrollbars-grid] > [data-overlayscrollbars-padding] > [data-overlayscrollbars-viewport] { + height: auto !important; + width: auto !important; +} + +.os-scrollbar { + contain: size layout; + contain: size layout style; + transition: opacity 0.15s, visibility 0.15s, top 0.15s, right 0.15s, bottom 0.15s, left 0.15s; + pointer-events: none; + position: absolute; + opacity: 0; + visibility: hidden; +} + +body > .os-scrollbar { + position: fixed; + z-index: 99999; +} + +.os-scrollbar-transitionless { + transition: none; +} + +.os-scrollbar-track { + position: relative; + direction: ltr !important; + padding: 0 !important; + border: none !important; +} + +.os-scrollbar-handle { + position: absolute; +} + +.os-scrollbar-track, +.os-scrollbar-handle { + pointer-events: none; + width: 100%; + height: 100%; +} + +.os-scrollbar.os-scrollbar-track-interactive .os-scrollbar-track, +.os-scrollbar.os-scrollbar-handle-interactive .os-scrollbar-handle { + pointer-events: auto; + touch-action: none; +} + +.os-scrollbar-horizontal { + bottom: 0; + left: 0; +} + +.os-scrollbar-vertical { + top: 0; + right: 0; +} + +.os-scrollbar-rtl.os-scrollbar-horizontal { + right: 0; +} + +.os-scrollbar-rtl.os-scrollbar-vertical { + right: auto; + left: 0; +} + +.os-scrollbar-visible, +.os-scrollbar-interaction.os-scrollbar-visible { + opacity: 1; + visibility: visible; +} + +.os-scrollbar-auto-hide.os-scrollbar-auto-hide-hidden { + opacity: 0; + visibility: hidden; +} + +.os-scrollbar-unusable, +.os-scrollbar-unusable *, +.os-scrollbar-wheel, +.os-scrollbar-wheel * { + pointer-events: none !important; +} + +.os-scrollbar-unusable .os-scrollbar-handle { + opacity: 0 !important; +} + +.os-scrollbar-horizontal .os-scrollbar-handle { + bottom: 0; +} + +.os-scrollbar-vertical .os-scrollbar-handle { + right: 0; +} + +.os-scrollbar-rtl.os-scrollbar-vertical .os-scrollbar-handle { + right: auto; + left: 0; +} + +.os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless, +.os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless.os-scrollbar-rtl { + left: 0; + right: 0; +} + +.os-scrollbar.os-scrollbar-vertical.os-scrollbar-cornerless, +.os-scrollbar.os-scrollbar-vertical.os-scrollbar-cornerless.os-scrollbar-rtl { + top: 0; + bottom: 0; +} + +.os-scrollbar { + --os-size: 0; + --os-padding-perpendicular: 0; + --os-padding-axis: 0; + --os-track-border-radius: 0; + --os-track-bg: none; + --os-track-bg-hover: none; + --os-track-bg-active: none; + --os-track-border: none; + --os-track-border-hover: none; + --os-track-border-active: none; + --os-handle-border-radius: 0; + --os-handle-bg: none; + --os-handle-bg-hover: none; + --os-handle-bg-active: none; + --os-handle-border: none; + --os-handle-border-hover: none; + --os-handle-border-active: none; + --os-handle-min-size: 33px; + --os-handle-max-size: none; + --os-handle-perpendicular-size: 100%; + --os-handle-perpendicular-size-hover: 100%; + --os-handle-perpendicular-size-active: 100%; + --os-handle-interactive-area-offset: 0; +} + +.os-scrollbar .os-scrollbar-track { + border: var(--os-track-border); + border-radius: var(--os-track-border-radius); + background: transparent; + transition: opacity 0.15s, background-color 0.15s, border-color 0.15s; +} +.os-scrollbar .os-scrollbar-track:hover { + border: var(--os-track-border-hover); + background: var(--os-track-bg-hover); +} +.os-scrollbar .os-scrollbar-track:active { + border: var(--os-track-border-active); + background: var(--os-track-bg-active); +} +.os-scrollbar .os-scrollbar-handle { + border: var(--os-handle-border); + border-radius: var(--os-handle-border-radius); + background: ${theme('hint')}; +} +.os-scrollbar .os-scrollbar-handle:before { + content: ""; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + display: block; +} +.os-scrollbar .os-scrollbar-handle:hover { + border: var(--os-handle-border-hover); + background: var(--os-handle-bg-hover); +} +.os-scrollbar .os-scrollbar-handle:active { + border: var(--os-handle-border-active); + background: var(--os-handle-bg-active); +} + +.os-scrollbar-horizontal { + padding: var(--os-padding-perpendicular) var(--os-padding-axis); + right: var(--os-size); + height: var(--os-size); +} +.os-scrollbar-horizontal.os-scrollbar-rtl { + left: var(--os-size); + right: 0; +} +.os-scrollbar-horizontal .os-scrollbar-handle { + min-width: var(--os-handle-min-size); + max-width: var(--os-handle-max-size); + height: var(--os-handle-perpendicular-size); + transition: opacity 0.15s, background-color 0.15s, border-color 0.15s, height 0.15s; +} +.os-scrollbar-horizontal .os-scrollbar-handle:before { + top: calc((var(--os-padding-perpendicular) + var(--os-handle-interactive-area-offset)) * -1); + bottom: calc(var(--os-padding-perpendicular) * -1); +} +.os-scrollbar-horizontal:hover .os-scrollbar-handle { + height: var(--os-handle-perpendicular-size-hover); +} +.os-scrollbar-horizontal:active .os-scrollbar-handle { + height: var(--os-handle-perpendicular-size-active); +} + +.os-scrollbar-vertical { + padding: var(--os-padding-axis) var(--os-padding-perpendicular); + bottom: var(--os-size); + width: var(--os-size); +} +.os-scrollbar-vertical .os-scrollbar-handle { + min-height: var(--os-handle-min-size); + max-height: var(--os-handle-max-size); + width: var(--os-handle-perpendicular-size); + transition: opacity 0.15s, background-color 0.15s, border-color 0.15s, width 0.15s; +} +.os-scrollbar-vertical .os-scrollbar-handle:before { + left: calc((var(--os-padding-perpendicular) + var(--os-handle-interactive-area-offset)) * -1); + right: calc(var(--os-padding-perpendicular) * -1); +} +.os-scrollbar-vertical.os-scrollbar-rtl .os-scrollbar-handle:before { + right: calc((var(--os-padding-perpendicular) + var(--os-handle-interactive-area-offset)) * -1); + left: calc(var(--os-padding-perpendicular) * -1); +} +.os-scrollbar-vertical:hover .os-scrollbar-handle { + width: var(--os-handle-perpendicular-size-hover); +} +.os-scrollbar-vertical:active .os-scrollbar-handle { + width: var(--os-handle-perpendicular-size-active); +} + +/* NONE THEME: */ +[data-overlayscrollbars~=updating] > .os-scrollbar, +.os-theme-none.os-scrollbar { + display: none !important; +} + +/* DARK & LIGHT THEME: */ +.os-theme-dark, +.os-theme-light { + box-sizing: border-box; + --os-size: 10px; + --os-padding-perpendicular: 2px; + --os-padding-axis: 2px; + --os-track-border-radius: 10px; + --os-handle-interactive-area-offset: 4px; + --os-handle-border-radius: 10px; +} + +.os-theme-dark { + --os-handle-bg: rgba(0, 0, 0, 0.44); + --os-handle-bg-hover: rgba(0, 0, 0, 0.55); + --os-handle-bg-active: rgba(0, 0, 0, 0.66); +} + +.os-theme-light { + --os-handle-bg: rgba(255, 255, 255, 0.44); + --os-handle-bg-hover: rgba(255, 255, 255, 0.55); + --os-handle-bg-active: rgba(255, 255, 255, 0.66); +} + +.os-no-css-vars.os-theme-dark.os-scrollbar .os-scrollbar-handle, .os-no-css-vars.os-theme-light.os-scrollbar .os-scrollbar-handle { + border-radius: 10px; +} +.os-no-css-vars.os-theme-dark.os-scrollbar .os-scrollbar-track, .os-no-css-vars.os-theme-light.os-scrollbar .os-scrollbar-track { + border-radius: 10px; +} +.os-no-css-vars.os-theme-dark.os-scrollbar .os-scrollbar-handle, .os-no-css-vars.os-theme-light.os-scrollbar .os-scrollbar-handle { + border-radius: 10px; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-horizontal, .os-no-css-vars.os-theme-light.os-scrollbar-horizontal { + padding: 2px 2px; + right: 10px; + height: 10px; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-horizontal.os-scrollbar-cornerless, .os-no-css-vars.os-theme-light.os-scrollbar-horizontal.os-scrollbar-cornerless { + right: 0; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-horizontal.os-scrollbar-rtl, .os-no-css-vars.os-theme-light.os-scrollbar-horizontal.os-scrollbar-rtl { + left: 10px; + right: 0; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-horizontal.os-scrollbar-rtl.os-scrollbar-cornerless, .os-no-css-vars.os-theme-light.os-scrollbar-horizontal.os-scrollbar-rtl.os-scrollbar-cornerless { + left: 0; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-horizontal .os-scrollbar-handle, .os-no-css-vars.os-theme-light.os-scrollbar-horizontal .os-scrollbar-handle { + min-width: 33px; + max-width: none; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-horizontal .os-scrollbar-handle:before, .os-no-css-vars.os-theme-light.os-scrollbar-horizontal .os-scrollbar-handle:before { + top: calc(( + 2px + 4px + ) * -1); + bottom: calc(2px * -1); +} +.os-no-css-vars.os-theme-dark.os-scrollbar-vertical, .os-no-css-vars.os-theme-light.os-scrollbar-vertical { + padding: 2px 2px; + bottom: 10px; + width: 10px; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-vertical.os-scrollbar-cornerless, .os-no-css-vars.os-theme-light.os-scrollbar-vertical.os-scrollbar-cornerless { + bottom: 0; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-vertical .os-scrollbar-handle, .os-no-css-vars.os-theme-light.os-scrollbar-vertical .os-scrollbar-handle { + min-height: 33px; + max-height: none; +} +.os-no-css-vars.os-theme-dark.os-scrollbar-vertical .os-scrollbar-handle:before, .os-no-css-vars.os-theme-light.os-scrollbar-vertical .os-scrollbar-handle:before { + left: calc(( + 2px + 4px + ) * -1); + right: calc(2px * -1); +} +.os-no-css-vars.os-theme-dark.os-scrollbar-vertical.os-scrollbar-rtl .os-scrollbar-handle:before, .os-no-css-vars.os-theme-light.os-scrollbar-vertical.os-scrollbar-rtl .os-scrollbar-handle:before { + right: calc(( + 2px + 4px + ) * -1); + left: calc(2px * -1); +} +.os-no-css-vars.os-theme-dark .os-scrollbar-handle { + background: rgba(0, 0, 0, 0.44); +} +.os-no-css-vars.os-theme-dark:hover .os-scrollbar-handle { + background: rgba(0, 0, 0, 0.55); +} +.os-no-css-vars.os-theme-dark:active .os-scrollbar-handle { + background: rgba(0, 0, 0, 0.66); +} +.os-no-css-vars.os-theme-light .os-scrollbar-handle { + background: rgba(255, 255, 255, 0.44); +} +.os-no-css-vars.os-theme-light:hover .os-scrollbar-handle { + background: rgba(255, 255, 255, 0.55); +} +.os-no-css-vars.os-theme-light:active .os-scrollbar-handle { + background: rgba(255, 255, 255, 0.66); +} ` export default ScrollBarStyle diff --git a/src/widgets/UserList/UserItem.tsx b/src/widgets/UserList/UserItem.tsx new file mode 100644 index 000000000..45b47c352 --- /dev/null +++ b/src/widgets/UserList/UserItem.tsx @@ -0,0 +1,30 @@ +import { FC } from 'react' + +import type { TUser } from '@/spec' + +import { assetSrc } from '@/helper' +import useAvatarLayout from '@/hooks/useAvatarLayout' +import { Wrapper, Avatar, Main, Header, Title, Login, Bio } from './styles/user_item' + +type TProps = { + user: TUser +} + +const UserItem: FC = ({ user }) => { + const avatarLayout = useAvatarLayout() + + return ( + + +
+
+ {user.nickname} + {user.login} +
+ {user.bio} +
+
+ ) +} + +export default UserItem diff --git a/src/widgets/UserList/index.tsx b/src/widgets/UserList/index.tsx new file mode 100644 index 000000000..3b058cf50 --- /dev/null +++ b/src/widgets/UserList/index.tsx @@ -0,0 +1,20 @@ +import { FC } from 'react' + +import { mockUsers } from '@/mock' + +import UserItem from './UserItem' +import { Wrapper } from './styles' + +const UserList: FC = () => { + const users = mockUsers(18) + + return ( + + {users.map((user) => ( + + ))} + + ) +} + +export default UserList diff --git a/src/widgets/UserList/styles/index.ts b/src/widgets/UserList/styles/index.ts new file mode 100644 index 000000000..6f4133fd2 --- /dev/null +++ b/src/widgets/UserList/styles/index.ts @@ -0,0 +1,14 @@ +import styled from 'styled-components' + +import css, { theme } from '@/css' + +export const Wrapper = styled.div` + ${css.column('align-center')}; + width: 100%; + gap: 22px 0; + padding: 0 50px; +` +export const Title = styled.div` + color: ${theme('article.title')}; + font-size: 13px; +` diff --git a/src/widgets/UserList/styles/user_item.ts b/src/widgets/UserList/styles/user_item.ts new file mode 100644 index 000000000..adef6a8c1 --- /dev/null +++ b/src/widgets/UserList/styles/user_item.ts @@ -0,0 +1,47 @@ +import styled from 'styled-components' + +import type { TAvatarLayout } from '@/spec' +import { AVATAR_LAYOUT } from '@/constant/layout' +import css, { theme } from '@/css' +import Img from '@/Img' + +export const Wrapper = styled.div` + ${css.row('align-start')}; + width: 100%; + + &:last-child { + margin-bottom: 50px; + } +` +export const Avatar = styled(Img)<{ $avatarLayout: TAvatarLayout }>` + ${css.size(32)}; + margin-top: 8px; + border-radius: ${({ $avatarLayout }) => + $avatarLayout === AVATAR_LAYOUT.SQUARE ? '6px' : '100%'}; +` +export const Main = styled.div` + ${css.column()}; + margin-left: 12px; +` +export const Header = styled.div` + ${css.row('align-center')}; +` +export const Title = styled.div` + color: ${theme('article.title')}; + font-weight: 500; + font-size: 16px; +` +export const Login = styled.div` + color: ${theme('hint')}; + font-size: 13px; + margin-left: 5px; + &:before { + content: '@'; + font-size: 11px; + margin-right: 1px; + } +` +export const Bio = styled.div` + color: ${theme('article.digest')}; + font-size: 13px; +` diff --git a/src/widgets/UserListModal/index.tsx b/src/widgets/UserListModal/index.tsx new file mode 100644 index 000000000..f6919248c --- /dev/null +++ b/src/widgets/UserListModal/index.tsx @@ -0,0 +1,27 @@ +import { FC } from 'react' +import { observer } from 'mobx-react-lite' + +import useUserListModal from '@/hooks/useUserListModal' +import Modal from '@/widgets/Modal' +import CustomScroller from '@/widgets/CustomScroller' +import UserList from '@/widgets/UserList' + +import { Wrapper, ScrollWrapper } from './styles' + +const UserListModal: FC = () => { + const { show, onClose } = useUserListModal() + + return ( + + +

List Modal

+ + + + +
+
+ ) +} + +export default observer(UserListModal) diff --git a/src/widgets/UserListModal/styles/index.ts b/src/widgets/UserListModal/styles/index.ts new file mode 100644 index 000000000..9fb7fea76 --- /dev/null +++ b/src/widgets/UserListModal/styles/index.ts @@ -0,0 +1,19 @@ +import styled from 'styled-components' + +import css, { theme } from '@/css' + +export const Wrapper = styled.div` + ${css.column('align-center')}; + width: 100%; + height: 480px; +` +export const ScrollWrapper = styled.div` + position: relative; + width: 100%; + height: 480px; + overflow-y: scroll; +` +export const Title = styled.div` + color: ${theme('article.title')}; + font-size: 13px; +` diff --git a/utils/constant/event.ts b/utils/constant/event.ts index dcb73052e..4099200b5 100755 --- a/utils/constant/event.ts +++ b/utils/constant/event.ts @@ -77,6 +77,9 @@ const EVENT = { // subscribe SUBSCRIBE: 'SUBSCRIBE', AUTH: 'AUTH', + + // + LIST_USER_MODAL: 'LIST_USER_MODAL', } export default EVENT diff --git a/utils/constant/filter.ts b/utils/constant/filter.ts index 2326fe4a5..e8157d54c 100755 --- a/utils/constant/filter.ts +++ b/utils/constant/filter.ts @@ -4,30 +4,6 @@ const FILTER = { THIS_WEEK: 'THIS_WEEK', THIS_MONTH: 'THIS_MONTH', THIS_YEAR: 'THIS_YEAR', - - // sort - MOST_VIEWS: 'MOST_VIEWS', - MOST_STARS: 'MOST_STARS', - MOST_FAVORITES: 'MOST_FAVORITES', - MOST_COMMENTS: 'MOST_COMMENTS', - - ASC_INSERTED: 'ASC_INSERTED', - DESC_INSERTED: 'DESC_INSERTED', - MOST_LIKES: 'MOST_LIKES', - MOST_DISLIKES: 'MOST_DISLIKES', - - MOST_GITHUB_STAR: 'MOST_GITHUB_STAR', - MOST_GITHUB_FORK: 'MOST_GITHUB_FORK', - MOST_GITHUB_WATCH: 'MOST_GITHUB_WATCH', - - // length - MOST_WORDS: 'MOST_WORDS', - LEAST_WORDS: 'LEAST_WORDS', - - // READ - READ: 'TRUE', - UNREAD: 'FLASE', - ALL: 'ALL', } export default FILTER diff --git a/utils/constant/type.ts b/utils/constant/type.ts index eeae528ae..00676a8b8 100755 --- a/utils/constant/type.ts +++ b/utils/constant/type.ts @@ -25,16 +25,6 @@ const TYPE = { CUR_THEME: 'cur_theme', // actions - FAVORITE: 'FAVORITE', - STAR: 'STAR', - - USER_LISTER_FAVORITES: 'USER_LISTER_FAVORITES', - USER_LISTER_STARS: 'USER_LISTER_STARS', - USER_LISTER_COMMUNITY_EDITORS: 'USER_LISTER_COMMUNITY_EDITORS', - USER_LISTER_COMMUNITY_SUBSCRIBERS: 'USER_LISTER_COMMUNITY_SUBSCRIBERS', - - USER_LISTER_FOLLOWINGS: 'USER_LISTER_FOLLOWINGS', - USER_LISTER_FOLLOWERS: 'USER_LISTER_FOLLOWERS', // drawer types DRAWER: { @@ -55,9 +45,6 @@ const TYPE = { // custom background editor CUSTOM_BG_EDITOR: 'CUSTOM_BG_EDITOR', - // user lister - USER_LISTER: 'USER_LISTER', - // passport PASSPORT_EDITOR: 'PASSPORT_EDITOR', @@ -67,6 +54,9 @@ const TYPE = { // tag CREATE_TAG: 'CREATE_TAG', EDIT_TAG: 'EDIT_TAG', + + // + LIST_USERS: 'LIST_USERS', }, REPORT: { @@ -101,11 +91,7 @@ const TYPE = { NOT_FOUND: 'NOT_FOUND', RESULT: 'RESULT', RESULT_EMPTY: 'RESULT_EMPTY', - // filters - ASC_INSERTED: 'ASC_INSERTED', - DESC_INSERTED: 'DESC_INSERTED', - MOST_LIKES: 'MOST_LIKES', - MOST_DISLIKES: 'MOST_DISLIKES', + // } export default TYPE diff --git a/utils/signal.ts b/utils/signal.ts index 26b6f84e2..7361da07b 100644 --- a/utils/signal.ts +++ b/utils/signal.ts @@ -106,9 +106,19 @@ export const setTag = (): void => { send(EVENT.SET_TAG, {}) } -export const listUsers = (data): void => { - const type = TYPE.DRAWER.USER_LISTER - send(EVENT.DRAWER.OPEN, { type, data }) +/** + * list users + * type: modal or drawer + */ +export const listUsers = (type: 'modal' | 'drawer'): void => { + if (type === 'drawer') { + const type = TYPE.DRAWER.LIST_USERS + send(EVENT.DRAWER.OPEN, { type }) + + return + } + + send(EVENT.LIST_USER_MODAL, { type }) } export const callPassportEditor = (): void => { diff --git a/utils/themes/skins/day.ts b/utils/themes/skins/day.ts index c0dded486..6208b9b1d 100644 --- a/utils/themes/skins/day.ts +++ b/utils/themes/skins/day.ts @@ -53,7 +53,6 @@ const day = { lineDivider: '#acacacc9', hoverBorder: hoverBg, hoverLinear: 'linear-gradient(315deg, rgba(255, 255, 255, 0) 0%, #fafafa 100%)', - activeLinear: 'linear-gradient(315deg,rgba(255,255,255,0) 0%,#f1f1f1 70%)', menuActive: '#e9e9e991', linkHover: lighten(link, 5), heightIcon: '#e48a3d', diff --git a/utils/themes/skins/night.ts b/utils/themes/skins/night.ts index bc28e916d..671b475e0 100644 --- a/utils/themes/skins/night.ts +++ b/utils/themes/skins/night.ts @@ -54,7 +54,6 @@ const night = { savingBarBg: '#f7f7f7', hoverBorder: '#393939', hoverLinear: 'linear-gradient(315deg, rgb(104 104 104 / 0%) 0%, #2c2c2c 100%);', - activeLinear: 'linear-gradient(315deg,rgba(255,255,255,0) 0%,#343434 70%)', menuActive: '#e9e9e991', linkHover: lighten(link, 5), heightIcon: '#e48a3d',