Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: pull out state from MainPage #199

Merged
merged 2 commits into from
Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions src/controller/MainPageDataController.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useEffect, useState } from 'react';
import MainPage, { MainPageProps, MainPageState } from '../pages/MainPage';
import MainPage from '../pages/MainPage';
import { MappingProps } from '../../server/controller/DocumentController';
import MainPageList from '../pages/MainPageList';
import { message } from 'antd';
import { SelectValue } from 'antd/lib/select';
import { ExHentaiInfoItem } from '../../server/controller/ExhentaiController';
import EditForm, { FormProps } from '../pages/EditForm';
import ExhentaiList from './ExHentaiListDataController';
import { useResize } from '../hooks/useResize';

export interface SiderProps {
key: string;
Expand Down Expand Up @@ -76,6 +77,10 @@ const MainPageDataController = () => {
exhentaiListTargetDataSource,
setExhentaiListTargetDataSource,
] = useState([]);
const [siderOpenKey, setSiderOpenKey] = useState('all');
const [siderSelectedKey, setSiderSelectedKey] = useState('all');

useResize();

useEffect(() => {
checkLocalStatus(getExhentaiDateSet);
Expand Down Expand Up @@ -185,17 +190,24 @@ const MainPageDataController = () => {
setFormVisible(false);
};

const renderContent = (
mainPageProps: MainPageProps,
mainPageState: MainPageState,
) => {
const renderContent = () => {
if (isExhentai && ExhentaiList) {
return <ExhentaiList dataSource={exhentaiListTargetDataSource} />;
}
return <MainPageList props={mainPageProps} state={mainPageState} />;
return (
<MainPageList
siderSelectedKey={siderSelectedKey}
onListItemClick={handleListItemClick}
onDelete={handleDelete}
dataSource={dataSource}
onEdit={handleEdit}
/>
);
};

const handleMenuClick = (keyPath: string[]) => {
setSiderOpenKey(keyPath[1]);
setSiderSelectedKey(keyPath[0]);
setIsExhentai(keyPath.length === 1 && keyPath[0] === 'ex-hentai-module');
};

Expand All @@ -210,17 +222,16 @@ const MainPageDataController = () => {
return (
<>
<MainPage
dataSource={dataSource}
onEdit={handleEdit}
onDelete={handleDelete}
onMenuClick={handleMenuClick}
menuData={menuData}
onExhentaiDownload={handleExhentaiDownload}
renderContent={renderContent}
onListItemClick={handleListItemClick}
isLocal={isLocal}
exhentaiDateSet={exhentaiDateSet}
onExhentaiSelectChange={handleExhentaiSelectChange}
onEdit={handleEdit}
siderOpenKey={siderOpenKey}
siderSelectedKey={siderSelectedKey}
/>
<EditForm
visible={formVisible}
Expand Down
19 changes: 19 additions & 0 deletions src/hooks/useResize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useEffect, useState } from 'react';

export function useResize() {
const [, setWidth] = useState(document.body.clientWidth);
const [, setHeight] = useState(document.body.clientHeight);

useEffect(() => {
const handleResize = () => {
setWidth(document.body.clientWidth);
setHeight(document.body.clientHeight);
};

window.addEventListener('resize', handleResize);

return () => {
window.removeEventListener('resize', handleResize);
};
});
}
189 changes: 68 additions & 121 deletions src/pages/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,127 +1,81 @@
import React, { Component } from 'react';
/* eslint-disable react/prop-types */
import React from 'react';
import './css/MainPage.css';
import { Menu, Layout } from 'antd';
const { SubMenu } = Menu;
const { Content, Footer, Sider, Header } = Layout;
const { Content, Footer, Sider } = Layout;
import { SiderProps } from '../controller/MainPageDataController';
import { MappingProps } from '../../server/controller/DocumentController';
import { SelectValue } from 'antd/lib/select';
import MainPageHeader from './MainPageHeader';

export interface MainPageProps {
dataSource: MappingProps[];
onEdit: (dataItem?: any, visible?: boolean) => void;
onDelete?: (dataItem: any) => void;
menuData: SiderProps[];
menuData?: SiderProps[];
onExhentaiDownload: (event: React.KeyboardEvent<HTMLInputElement>) => void;
renderContent?: (
props: MainPageProps,
state: MainPageState,
event?: any,
) => React.ReactNode;
onMenuClick: (keyPath: string[]) => void;
onListItemClick: ({
category,
id,
}: {
category: 'mapping' | 'markdown';
id: string;
}) => void;
isLocal: boolean;
renderContent?: () => React.ReactNode;
onMenuClick?: (keyPath: string[]) => void;
isLocal?: boolean;
exhentaiDateSet: string[];
onExhentaiSelectChange: (value: SelectValue) => void;
siderOpenKey?: string;
siderSelectedKey?: string;
}
export interface MainPageState {
siderOpenKey: string;
siderSelectedKey: string;
DynamicHeader: any;
}
let MainPageHeader: any;

export default class MainPage extends Component<MainPageProps, MainPageState> {
static getDerivedStateFromProps(
prevProps: MainPageProps,
prevState: MainPageState,
) {
const { menuData, isLocal } = prevProps;
const { siderSelectedKey, DynamicHeader } = prevState;
if (menuData.length > 0 && !siderSelectedKey) {
return {
siderOpenKey: menuData[0].title,
siderSelectedKey: menuData[0].title,
};
}
if (isLocal && !DynamicHeader) {
// todo: replace require with import()
// if replace require with import now, it would cause memory leak
// have checked https://github.com/webpack/webpack/issues/4292#issuecomment-280165950
// but no effect, so use require temporarily
// 1. this function should be moved to componentDidUpdate
// 2. should check unexpected shaking of Header
MainPageHeader = require('./MainPageHeader').default;
return {
DynamicHeader: <MainPageHeader Header={Header} {...prevProps} />,
};
}
if (isLocal && DynamicHeader) {
return {
DynamicHeader: <MainPageHeader Header={Header} {...prevProps} />,
};
}
return null;
}

state: MainPageState = {
siderOpenKey: '',
siderSelectedKey: '',
DynamicHeader: null,
};

componentDidMount() {
window.onresize = () => this.setState({});
}

componentWillUnmount() {
MainPageHeader = null;
}
const renderFooter = () => (
<Footer style={{ textAlign: 'center' }}>
<div>
你睡了一下午,醒的时候屋子里黑漆漆、一点声音都没有。抬头望望窗外,天还没完全黑。四处摸了摸,在枕头下找到手机。打开后屏幕亮起,干净,没有一条消息
</div>
<div>
打开电脑,打开 github。pull request 写得很菜,连 core
都在喷你,但忽然就不孤独了
</div>
</Footer>
);

handleMenuClick = ({ keyPath }: { keyPath: string[] }) => {
this.props.onMenuClick(keyPath);
this.setState({
siderOpenKey: keyPath[1],
siderSelectedKey: keyPath[0],
});
const MainPage = ({
onMenuClick,
siderSelectedKey,
menuData,
renderContent,
isLocal,
onExhentaiDownload,
onEdit,
exhentaiDateSet,
onExhentaiSelectChange,
}: MainPageProps) => {
const handleMenuClick = ({ keyPath }: { keyPath: string[] }) => {
onMenuClick && onMenuClick(keyPath);
};

renderSider = () => {
const { menuData } = this.props;
const { siderSelectedKey } = this.state;
const renderSider = () => {
return (
<Sider theme="light" collapsible collapsedWidth={0}>
<Menu
selectedKeys={[siderSelectedKey]}
selectedKeys={[siderSelectedKey || '']}
mode="inline"
onClick={this.handleMenuClick}
onClick={handleMenuClick}
>
{menuData.map((item: any) => {
const { key, title, children } = item;
if (!children) {
return <Menu.Item key={key}>{title}</Menu.Item>;
}
return (
<SubMenu key={key} title={title}>
{children.map((jtem: any) => (
<Menu.Item key={jtem.key}>{jtem.value}</Menu.Item>
))}
</SubMenu>
);
})}
{menuData &&
menuData.map((item: any) => {
const { key, title, children } = item;
if (!children) {
return <Menu.Item key={key}>{title}</Menu.Item>;
}
return (
<SubMenu key={key} title={title}>
{children.map((jtem: any) => (
<Menu.Item key={jtem.key}>{jtem.value}</Menu.Item>
))}
</SubMenu>
);
})}
</Menu>
</Sider>
);
};

renderContent = () => {
const { renderContent, isLocal } = this.props;
const renderRealContent = () => {
const headerHeight = isLocal ? 48 : 0;
const wrapperHeight = document.body.clientHeight - 90 - headerHeight;
return (
Expand All @@ -135,36 +89,29 @@ export default class MainPage extends Component<MainPageProps, MainPageState> {
}}
className="main-page-content-wrapper"
>
{renderContent && renderContent(this.props, this.state)}
{renderContent && renderContent()}
</div>
</Content>
);
};

renderFooter = () => (
<Footer style={{ textAlign: 'center' }}>
<div>
你睡了一下午,醒的时候屋子里黑漆漆、一点声音都没有。抬头望望窗外,天还没完全黑。四处摸了摸,在枕头下找到手机。打开后屏幕亮起,干净,没有一条消息
</div>
<div>
打开电脑,打开 github。pull request 写得很菜,连 core
都在喷你,但忽然就不孤独了
</div>
</Footer>
);

renderHeader = () => {
return this.state.DynamicHeader;
};

render = () => (
return (
<Layout className="MainPage">
{this.renderSider()}
{renderSider()}
<Layout>
{this.renderHeader()}
{this.renderContent()}
{this.renderFooter()}
{isLocal && (
<MainPageHeader
onExhentaiDownload={onExhentaiDownload}
onEdit={onEdit}
exhentaiDateSet={exhentaiDateSet}
onExhentaiSelectChange={onExhentaiSelectChange}
/>
)}
{renderRealContent()}
{renderFooter()}
</Layout>
</Layout>
);
}
};

export default MainPage;
6 changes: 3 additions & 3 deletions src/pages/MainPageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React, { useState } from 'react';
import { Button, Input, Select } from 'antd';
import { Button, Input, Select, Layout } from 'antd';
import { MainPageProps } from './MainPage';
import { Plus } from '@ant-design/icons';
import { SelectValue } from 'antd/lib/select';
const { Option } = Select;
const { Header } = Layout;

const MainPageHeader = ({
Header,
onExhentaiDownload,
onEdit,
exhentaiDateSet,
onExhentaiSelectChange,
}: MainPageProps & { Header: any }) => {
}: MainPageProps) => {
const [selectValue, setSelectValue] = useState();

const handleSelectChange = (value: SelectValue) => {
Expand Down
26 changes: 18 additions & 8 deletions src/pages/MainPageList.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import React from 'react';
import { List, Dropdown, Menu } from 'antd';
import { format } from 'date-fns';
import { MainPageProps, MainPageState } from './MainPage';
import { Apartment, FileMarkdown } from '@ant-design/icons';
import { MappingProps } from '../../server/controller/DocumentController';

const MainPageList = ({
props,
state,
onDelete,
siderSelectedKey,
dataSource,
onEdit,
onListItemClick,
}: {
props: MainPageProps;
state: MainPageState;
siderSelectedKey: string;
onDelete?: (dataItem: any) => void;
dataSource: MappingProps[];
onEdit: (dataItem?: any, visible?: boolean) => void;
onListItemClick: ({
category,
id,
}: {
category: 'mapping' | 'markdown';
id: string;
}) => void;
}) => {
const { dataSource, onDelete, onEdit } = props;
const { siderSelectedKey } = state;
return (
<List
dataSource={
Expand Down Expand Up @@ -44,7 +54,7 @@ const MainPageList = ({
<List.Item
className="list-item"
onClick={() =>
props.onListItemClick({
onListItemClick({
category: item.category,
id: item.id,
})
Expand Down
Loading