diff options
Diffstat (limited to 'vnext/src')
-rw-r--r-- | vnext/src/App.js | 58 | ||||
-rw-r--r-- | vnext/src/ui/Feeds.js | 49 | ||||
-rw-r--r-- | vnext/src/ui/Header.js | 8 | ||||
-rw-r--r-- | vnext/src/ui/Login.js | 8 | ||||
-rw-r--r-- | vnext/src/ui/Post.js | 6 |
5 files changed, 55 insertions, 74 deletions
diff --git a/vnext/src/App.js b/vnext/src/App.js index b56e0300..79fde2d1 100644 --- a/vnext/src/App.js +++ b/vnext/src/App.js @@ -1,5 +1,5 @@ import { useState, useEffect, useRef } from 'react'; -import { Route, Link, Switch } from 'react-router-dom'; +import { Route, Link, Routes } from 'react-router-dom'; import { useScroll, useRafState } from 'react-use'; import qs from 'qs'; @@ -183,47 +183,21 @@ export default function App({ footer }) { </aside> } <section id="content" ref={contentRef} className={scrollState.top ? elClassTop : ''}> - <Switch> - <Route exact path="/"> - <Discussions visitor={visitor} /> - </Route> - <Route exact path="/home"> - <Home visitor={visitor} /> - </Route> - <Route exact path="/discover"> - <Discover visitor={visitor} /> - </Route> - <Route exact path="/settings"> - <Settings visitor={visitor} onChange={auth} /> - </Route> - <Route exact path="/login"> - <Login visitor={visitor} onAuth={auth} /> - </Route> - <Route exact path="/post"> - <Post visitor={visitor} /> - </Route> - <Route exact path="/pm"> - <Contacts visitor={visitor} /> - </Route> - <Route exact path="/pm/:user"> - <Chat connection={eventSource} visitor={visitor} /> - </Route> - <Route exact path="/:user/friends"> - <Friends /> - </Route> - <Route exact path="/:user/readers"> - <Readers /> - </Route> - <Route exact path="/:user"> - <Blog visitor={visitor} /> - </Route> - <Route exact path="/tag/:tag"> - <Tag visitor={visitor} /> - </Route> - <Route exact path="/:user/:mid"> - <Thread connection={eventSource} visitor={visitor} /> - </Route> - </Switch> + <Routes> + <Route exact path="/" element={<Discussions visitor={visitor} />} /> + <Route exact path="/home" element={<Home visitor={visitor} />} /> + <Route exact path="/discover" element={<Discover visitor={visitor} />} /> + <Route exact path="/settings" element={<Settings visitor={visitor} onChange={auth} />} /> + <Route exact path="/login" element={<Login visitor={visitor} onAuth={auth} />} /> + <Route exact path="/post" element={<Post visitor={visitor} />} /> + <Route exact path="/pm" element={<Contacts visitor={visitor} />} /> + <Route exact path="/pm/:user" element={<Chat connection={eventSource} visitor={visitor} />} /> + <Route exact path="/:user/friends" element={<Friends />} /> + <Route exact path="/:user/readers" element={<Readers />} /> + <Route exact path="/:user" element={<Blog visitor={visitor} />} /> + <Route exact path="/tag/:tag" element={<Tag visitor={visitor} />} /> + <Route exact path="/:user/:mid" element={<Thread connection={eventSource} visitor={visitor} />} /> + </Routes> </section> </div> </> diff --git a/vnext/src/ui/Feeds.js b/vnext/src/ui/Feeds.js index d6813130..c9199fa6 100644 --- a/vnext/src/ui/Feeds.js +++ b/vnext/src/ui/Feeds.js @@ -1,5 +1,5 @@ -import { useState, useEffect } from 'react'; -import { Link, useLocation, useHistory, useParams } from 'react-router-dom'; +import { useState, useEffect, useLayoutEffect } from 'react'; +import { Link, useLocation, useParams, Navigate } from 'react-router-dom'; import qs from 'qs'; import moment from 'moment'; @@ -25,6 +25,19 @@ import { getMessages } from '../api'; * @property {import('../api').Message[]=} msgs */ +function RequireAuth({ visitor, children }) { + let location = useLocation(); + if (!visitor.hash) { + // Redirect them to the /login page, but save the current location they were + // trying to go to when they were redirected. This allows us to send them + // along to that page after they login, which is a nicer user experience + // than dropping them off on the home page. + return <Navigate to="/login" state={{ from: location }} />; + } + + return children; +} + /** * @param {PageProps} props */ @@ -36,7 +49,7 @@ export function Discover({ visitor }) { search: search, pageParam: search.search ? 'page' : 'before_mid' }; - return (<Feed authRequired={false} query={query} visitor={visitor} />); + return (<Feed query={query} visitor={visitor} />); } /** @@ -47,7 +60,7 @@ export function Discussions({ visitor }) { baseUrl: '/api/messages/discussions', pageParam: 'to' }; - return (<Feed authRequired={false} query={query} visitor={visitor} />); + return (<Feed query={query} visitor={visitor} />); } /** @@ -70,7 +83,7 @@ export function Blog({ visitor }) { <div className="msg-cont"> <UserInfo uname={user} /> </div> - <Feed authRequired={false} query={query} visitor={visitor} /> + <Feed query={query} visitor={visitor} /> </> ); } @@ -88,7 +101,7 @@ export function Tag({ visitor }) { }, pageParam: 'before_mid' }; - return (<Feed authRequired={false} query={query} visitor={visitor} />); + return (<Feed query={query} visitor={visitor} />); } /** @@ -99,12 +112,15 @@ export function Home({ visitor }) { baseUrl: '/api/home', pageParam: 'before_mid' }; - return (<Feed authRequired={true} query={query} visitor={visitor} />); + return ( + <RequireAuth visitor={visitor}> + <Feed query={query} visitor={visitor} /> + </RequireAuth> + ); } /** * @typedef {Object} FeedState - * @property { boolean } authRequired * @property { import('../api').SecureUser } visitor * @property { import('../api').Message[]= } msgs * @property { Query} query @@ -113,11 +129,9 @@ export function Home({ visitor }) { /** * @param {FeedState} props */ -function Feed({ visitor, query, authRequired }) { +function Feed({ visitor, query }) { const location = useLocation(); - const history = useHistory(); const [state, setState] = useState({ - authRequired: authRequired, hash: visitor.hash, msgs: [], nextpage: null, @@ -125,7 +139,6 @@ function Feed({ visitor, query, authRequired }) { tag: '' }); const [loading, setLoading] = useState(true); - useEffect(() => { setLoading(true); const filter = location.search.substring(1); @@ -135,23 +148,17 @@ function Feed({ visitor, query, authRequired }) { newFilter[pageParam] = pageValue; return `?${qs.stringify(newFilter)}`; }; - document.body.scrollTop = 0; - document.documentElement.scrollTop = 0; const filterParams = qs.parse(filter); let params = Object.assign({}, filterParams || {}, query.search || {}); let url = query.baseUrl; - if (state.hash) { - params.hash = state.hash; - } - if (!params.hash && state.authRequired) { - history.push('/'); - } getMessages(url, params) .then(response => { const { data } = response; const { pageParam } = query; const lastMessage = data.slice(-1)[0] || {}; const nextpage = getPageParam(pageParam, lastMessage, filterParams); + document.body.scrollTop = 0; + document.documentElement.scrollTop = 0; setState((prevState) => { return { ...prevState, @@ -169,7 +176,7 @@ function Feed({ visitor, query, authRequired }) { }; }); }); - }, [location.search, state.hash, state.authRequired, history, query]); + }, [location.search, query]); return (state.msgs.length > 0 ? ( <div className="msgs"> { diff --git a/vnext/src/ui/Header.js b/vnext/src/ui/Header.js index 1574a489..3162c9ea 100644 --- a/vnext/src/ui/Header.js +++ b/vnext/src/ui/Header.js @@ -1,12 +1,12 @@ import { memo, useCallback } from 'react'; -import { Link, useHistory } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import Icon from './Icon'; import { UserLink } from './UserInfo'; import SearchBox from './SearchBox'; function Header({ visitor, className }) { - const history = useHistory(); + const navigate = useNavigate(); /** * @param {string} searchString */ @@ -14,8 +14,8 @@ function Header({ visitor, className }) { let location = {}; location.pathname = '/discover'; location.search = `?search=${searchString}`; - history.push(location); - }, [history]); + navigate(location); + }, [navigate]); return ( <div id="header" className={className}> <div id="header_wrapper"> diff --git a/vnext/src/ui/Login.js b/vnext/src/ui/Login.js index fc3922c8..5a96c822 100644 --- a/vnext/src/ui/Login.js +++ b/vnext/src/ui/Login.js @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useLocation, useHistory } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import Icon from './Icon'; import Button from './Button'; @@ -22,15 +22,15 @@ import './Login.css'; function Login({ visitor, onAuth }) { const location = useLocation(); - const history = useHistory(); + const navigate = useNavigate(); useEffect(() => { if (visitor.hash) { const {retpath } = location.state || '/'; console.log(retpath); - history.push(retpath); + navigate(retpath); } - }, [history, location.state, visitor]); + }, [navigate, location.state, visitor]); const { register, handleSubmit, formState: { errors }, } = useForm(); diff --git a/vnext/src/ui/Post.js b/vnext/src/ui/Post.js index d8d841e1..a1d14ea0 100644 --- a/vnext/src/ui/Post.js +++ b/vnext/src/ui/Post.js @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { useLocation, useHistory } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import qs from 'qs'; @@ -13,7 +13,7 @@ import { post, update } from '../api'; */ export default function Post({ visitor }) { const location = useLocation(); - const history = useHistory(); + const navigate = useNavigate(); let draftMessage = (location.state || {}).draft || {}; let [draft, setDraft] = useState(draftMessage.body); let params = qs.parse(window.location.search.substring(1)); @@ -24,7 +24,7 @@ export default function Post({ visitor }) { .then(response => { if (response.status === 200) { const msg = response.data.newMessage; - history.push(`/${visitor.uname}/${msg.mid}`); + navigate(`/${visitor.uname}/${msg.mid}`); } }).catch(console.log); }; |