From 0d4e3079aa53f9553eb538951b6ebd6bf4a7a2ee Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 7 Aug 2020 18:27:04 +0800 Subject: Create home page for offline. --- Timeline/ClientApp/src/app/home/BoardWithUser.tsx | 102 +++++++++++++++++++++ .../ClientApp/src/app/home/BoardWithoutUser.tsx | 61 ++++++++++++ Timeline/ClientApp/src/app/home/Home.tsx | 88 ++++-------------- Timeline/ClientApp/src/app/home/OfflineBoard.tsx | 62 +++++++++++++ Timeline/ClientApp/src/app/home/TimelineBoard.tsx | 28 +++++- .../src/app/home/TimelineBoardAreaWithUser.tsx | 36 -------- .../src/app/home/TimelineBoardAreaWithoutUser.tsx | 26 ------ 7 files changed, 269 insertions(+), 134 deletions(-) create mode 100644 Timeline/ClientApp/src/app/home/BoardWithUser.tsx create mode 100644 Timeline/ClientApp/src/app/home/BoardWithoutUser.tsx create mode 100644 Timeline/ClientApp/src/app/home/OfflineBoard.tsx delete mode 100644 Timeline/ClientApp/src/app/home/TimelineBoardAreaWithUser.tsx delete mode 100644 Timeline/ClientApp/src/app/home/TimelineBoardAreaWithoutUser.tsx (limited to 'Timeline/ClientApp/src/app/home') diff --git a/Timeline/ClientApp/src/app/home/BoardWithUser.tsx b/Timeline/ClientApp/src/app/home/BoardWithUser.tsx new file mode 100644 index 00000000..3830104f --- /dev/null +++ b/Timeline/ClientApp/src/app/home/BoardWithUser.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { Row, Col } from 'reactstrap'; +import { useTranslation } from 'react-i18next'; + +import { UserWithToken } from '../data/user'; +import { TimelineInfo } from '../data/timeline'; + +import { getHttpTimelineClient } from '../http/timeline'; + +import TimelineBoard from './TimelineBoard'; +import OfflineBoard from './OfflineBoard'; + +const BoardWithUser: React.FC<{ user: UserWithToken }> = ({ user }) => { + const { t } = useTranslation(); + + const [ownTimelines, setOwnTimelines] = React.useState< + TimelineInfo[] | 'offline' | 'loading' + >('loading'); + const [joinTimelines, setJoinTimelines] = React.useState< + TimelineInfo[] | 'offline' | 'loading' + >('loading'); + + React.useEffect(() => { + let subscribe = true; + if (ownTimelines === 'loading') { + void getHttpTimelineClient() + .listTimeline({ relate: user.username, relateType: 'own' }) + .then( + (timelines) => { + if (subscribe) { + setOwnTimelines(timelines); + } + }, + () => { + setOwnTimelines('offline'); + } + ); + } + return () => { + subscribe = false; + }; + }, [user, ownTimelines]); + + React.useEffect(() => { + let subscribe = true; + if (joinTimelines === 'loading') { + void getHttpTimelineClient() + .listTimeline({ relate: user.username, relateType: 'join' }) + .then( + (timelines) => { + if (subscribe) { + setJoinTimelines(timelines); + } + }, + () => { + setJoinTimelines('offline'); + } + ); + } + return () => { + subscribe = false; + }; + }, [user, joinTimelines]); + + return ( + + {ownTimelines === 'offline' && joinTimelines === 'offline' ? ( + + { + setOwnTimelines('loading'); + setJoinTimelines('loading'); + }} + /> + + ) : ( + <> + + { + setOwnTimelines('loading'); + }} + /> + + + { + setJoinTimelines('loading'); + }} + /> + + + )} + + ); +}; + +export default BoardWithUser; diff --git a/Timeline/ClientApp/src/app/home/BoardWithoutUser.tsx b/Timeline/ClientApp/src/app/home/BoardWithoutUser.tsx new file mode 100644 index 00000000..4b30fcc4 --- /dev/null +++ b/Timeline/ClientApp/src/app/home/BoardWithoutUser.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Row, Col } from 'reactstrap'; + +import { TimelineInfo } from '../data/timeline'; + +import { getHttpTimelineClient } from '../http/timeline'; + +import TimelineBoard from './TimelineBoard'; +import OfflineBoard from './OfflineBoard'; + +const BoardWithoutUser: React.FC = () => { + const [publicTimelines, setPublicTimelines] = React.useState< + TimelineInfo[] | 'offline' | 'loading' + >('loading'); + + React.useEffect(() => { + let subscribe = true; + if (publicTimelines === 'loading') { + void getHttpTimelineClient() + .listTimeline({ visibility: 'Public' }) + .then( + (timelines) => { + if (subscribe) { + setPublicTimelines(timelines); + } + }, + () => { + setPublicTimelines('offline'); + } + ); + } + return () => { + subscribe = false; + }; + }, [publicTimelines]); + + return ( + + {publicTimelines === 'offline' ? ( + + { + setPublicTimelines('loading'); + }} + /> + + ) : ( + + { + setPublicTimelines('loading'); + }} + /> + + )} + + ); +}; + +export default BoardWithoutUser; diff --git a/Timeline/ClientApp/src/app/home/Home.tsx b/Timeline/ClientApp/src/app/home/Home.tsx index de25d5c1..b759fa50 100644 --- a/Timeline/ClientApp/src/app/home/Home.tsx +++ b/Timeline/ClientApp/src/app/home/Home.tsx @@ -4,16 +4,14 @@ import { Row, Container, Button, Col } from 'reactstrap'; import { useTranslation } from 'react-i18next'; import { useUser } from '../data/user'; -import { TimelineInfo } from '../data/timeline'; -import { getHttpTimelineClient } from '../http/timeline'; import AppBar from '../common/AppBar'; import SearchInput from '../common/SearchInput'; -import TimelineBoardAreaWithoutUser from './TimelineBoardAreaWithoutUser'; -import TimelineBoardAreaWithUser from './TimelineBoardAreaWithUser'; +import BoardWithoutUser from './BoardWithoutUser'; +import BoardWithUser from './BoardWithUser'; import TimelineCreateDialog from './TimelineCreateDialog'; -const Home: React.FC = (_) => { +const Home: React.FC = () => { const history = useHistory(); const { t } = useTranslation(); @@ -22,50 +20,6 @@ const Home: React.FC = (_) => { const [navText, setNavText] = React.useState(''); - const [publicTimelines, setPublicTimelines] = React.useState< - TimelineInfo[] | undefined - >(undefined); - const [ownTimelines, setOwnTimelines] = React.useState< - TimelineInfo[] | undefined - >(undefined); - const [joinTimelines, setJoinTimelines] = React.useState< - TimelineInfo[] | undefined - >(undefined); - - React.useEffect(() => { - let subscribe = true; - if (user == null) { - setOwnTimelines(undefined); - setJoinTimelines(undefined); - void getHttpTimelineClient() - .listTimeline({ visibility: 'Public' }) - .then((timelines) => { - if (subscribe) { - setPublicTimelines(timelines); - } - }); - } else { - setPublicTimelines(undefined); - void getHttpTimelineClient() - .listTimeline({ relate: user.username, relateType: 'own' }) - .then((timelines) => { - if (subscribe) { - setOwnTimelines(timelines); - } - }); - void getHttpTimelineClient() - .listTimeline({ relate: user.username, relateType: 'join' }) - .then((timelines) => { - if (subscribe) { - setJoinTimelines(timelines); - } - }); - } - return () => { - subscribe = false; - }; - }, [user]); - const [dialog, setDialog] = React.useState<'create' | null>(null); const goto = React.useCallback((): void => { @@ -78,14 +32,6 @@ const Home: React.FC = (_) => { } }, [navText, history]); - const openCreateDialog = React.useCallback(() => { - setDialog('create'); - }, []); - - const closeDialog = React.useCallback(() => { - setDialog(null); - }, []); - return ( <> @@ -101,7 +47,13 @@ const Home: React.FC = (_) => { placeholder="@crupest" additionalButton={ user != null && ( - ) @@ -111,16 +63,9 @@ const Home: React.FC = (_) => { {(() => { if (user == null) { - return ( - - ); + return ; } else { - return ( - - ); + return ; } })()} @@ -142,7 +87,14 @@ const Home: React.FC = (_) => { 公安备案 42112102000124 - {dialog === 'create' && } + {dialog === 'create' && ( + { + setDialog(null); + }} + /> + )} ); }; diff --git a/Timeline/ClientApp/src/app/home/OfflineBoard.tsx b/Timeline/ClientApp/src/app/home/OfflineBoard.tsx new file mode 100644 index 00000000..ca6d2a26 --- /dev/null +++ b/Timeline/ClientApp/src/app/home/OfflineBoard.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Trans } from 'react-i18next'; + +import { getAllCachedTimelineNames } from '../data/timeline'; + +import UserTimelineLogo from '../common/UserTimelineLogo'; +import TimelineLogo from '../common/TimelineLogo'; + +export interface OfflineBoardProps { + onReload: () => void; +} + +const OfflineBoard: React.FC = ({ onReload }) => { + const [timelines, setTimelines] = React.useState([]); + + React.useEffect(() => { + let subscribe = true; + void getAllCachedTimelineNames().then((t) => { + if (subscribe) setTimelines(t); + }); + return () => { + subscribe = false; + }; + }); + + return ( + <> + + 0 + { + onReload(); + e.preventDefault(); + }} + > + 1 + + 2 + + {timelines.map((timeline) => { + const isPersonal = timeline.startsWith('@'); + const url = isPersonal + ? `/users/${timeline.slice(1)}` + : `/timelines/${timeline}`; + return ( +
+ {isPersonal ? ( + + ) : ( + + )} + {timeline} +
+ ); + })} + + ); +}; + +export default OfflineBoard; diff --git a/Timeline/ClientApp/src/app/home/TimelineBoard.tsx b/Timeline/ClientApp/src/app/home/TimelineBoard.tsx index 2e017bf7..8f8f6387 100644 --- a/Timeline/ClientApp/src/app/home/TimelineBoard.tsx +++ b/Timeline/ClientApp/src/app/home/TimelineBoard.tsx @@ -2,6 +2,7 @@ import React from 'react'; import clsx from 'clsx'; import { Link } from 'react-router-dom'; import { Spinner } from 'reactstrap'; +import { Trans } from 'react-i18next'; import { TimelineInfo } from '../data/timeline'; @@ -10,25 +11,44 @@ import UserTimelineLogo from '../common/UserTimelineLogo'; export interface TimelineBoardProps { title?: string; - timelines?: TimelineInfo[]; + timelines: TimelineInfo[] | 'offline' | 'loading'; + onReload: () => void; className?: string; } -const TimelineBoard: React.FC = props => { +const TimelineBoard: React.FC = (props) => { const { title, timelines, className } = props; return (
{title != null &&

{title}

} {(() => { - if (timelines == null) { + if (timelines === 'loading') { return (
); + } else if (timelines === 'offline') { + return ( + + ); } else { - return timelines.map(timeline => { + return timelines.map((timeline) => { const { name } = timeline; const isPersonal = name.startsWith('@'); const url = isPersonal diff --git a/Timeline/ClientApp/src/app/home/TimelineBoardAreaWithUser.tsx b/Timeline/ClientApp/src/app/home/TimelineBoardAreaWithUser.tsx deleted file mode 100644 index a8603b9e..00000000 --- a/Timeline/ClientApp/src/app/home/TimelineBoardAreaWithUser.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { Row, Col } from 'reactstrap'; -import { useTranslation } from 'react-i18next'; - -import TimelineBoard from './TimelineBoard'; -import { TimelineInfo } from '../data/timeline'; - -interface TimelineBoardAreaWithUserProps { - ownTimelines?: TimelineInfo[]; - joinTimelines?: TimelineInfo[]; -} - -const TimelineBoardAreaWithUser: React.FC = ( - props -) => { - const { t } = useTranslation(); - - return ( - - - - - - - - - ); -}; - -export default TimelineBoardAreaWithUser; diff --git a/Timeline/ClientApp/src/app/home/TimelineBoardAreaWithoutUser.tsx b/Timeline/ClientApp/src/app/home/TimelineBoardAreaWithoutUser.tsx deleted file mode 100644 index dc05ff09..00000000 --- a/Timeline/ClientApp/src/app/home/TimelineBoardAreaWithoutUser.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { Row, Col } from 'reactstrap'; - -import { TimelineInfo } from '../data/timeline'; - -import TimelineBoard from './TimelineBoard'; - -interface TimelineBoardAreaWithoutUserProps { - publicTimelines?: TimelineInfo[]; -} - -const TimelineBoardAreaWithoutUser: React.FC = ( - props -) => { - const { publicTimelines } = props; - - return ( - - - - - - ); -}; - -export default TimelineBoardAreaWithoutUser; -- cgit v1.2.3