diff options
Diffstat (limited to 'vnext')
-rw-r--r-- | vnext/src/App.js | 84 | ||||
-rw-r--r-- | vnext/src/api/index.js | 6 | ||||
-rw-r--r-- | vnext/src/index.js | 49 | ||||
-rw-r--r-- | vnext/src/ui/Feeds.js | 1 | ||||
-rw-r--r-- | vnext/src/ui/Login.js | 4 | ||||
-rw-r--r-- | vnext/src/ui/Message.js | 8 | ||||
-rw-r--r-- | vnext/src/ui/VisitorContext.js | 17 |
7 files changed, 78 insertions, 91 deletions
diff --git a/vnext/src/App.js b/vnext/src/App.js index e723fe9c..c7849418 100644 --- a/vnext/src/App.js +++ b/vnext/src/App.js @@ -30,7 +30,7 @@ import { Toaster } from 'react-hot-toast' export default function App({ footer }) { let contentRef = useRef(null) - const [cookie, setCookie] = useCookies(['hash']) + const [, setCookie] = useCookies(['hash']) const [allTrends, setAllTrends] = useState([]) @@ -54,32 +54,13 @@ export default function App({ footer }) { }).catch(console.error) }, [setVisitor]) - const [hash, setHash] = useState(cookie.hash) - const [eventSource, setEventSource] = /** @param EventSource? */ useState({}) - /** - * @param {import("./api").SecureUser} visitor - */ - let auth = useCallback((visitor) => { - setVisitor(prevState => { - if (visitor.hash != prevState.hash) { - setHash(visitor.hash) - } - return visitor - }) - }, [setVisitor]) - useEffect(() => { let es - const anonymousUser = { - uid: 0 - } - if (hash) { - me().then(visitor => auth(visitor)) - .catch(() => setVisitor(anonymousUser)) + if (visitor) { if ('EventSource' in window) { - const eventParams = new URLSearchParams({ hash: hash }) + const eventParams = new URLSearchParams({ hash: visitor.hash }) let url = new URL(`https://juick.com/api/events?${eventParams.toString()}`) console.log(url.toString()) es = new EventSource(url.toString()) @@ -94,8 +75,6 @@ export default function App({ footer }) { es.addEventListener('msg', updateStatus) setEventSource(es) } - } else { - setVisitor(anonymousUser) } return (() => { if (es && es.removeEventListener) { @@ -103,7 +82,7 @@ export default function App({ footer }) { es.removeEventListener('msg', updateStatus) } }) - }, [auth, hash, setVisitor, updateStatus]) + }, [visitor, updateStatus]) useEffect(() => { const getTrends = async () => { @@ -121,32 +100,33 @@ export default function App({ footer }) { <div id="sidebar_wrapper"> { <nav id="global"> - {visitor.uid > 0 ? - <> - <div id="ctitle"> - <Avatar user={visitor} /> - </div> - <Link to={{ pathname: '/post' }}> - <Icon name="ei-pencil" size="s" /> - <span className="desktop">Post</span> - </Link> - <Link to="/?show=my"> - <Icon name="ei-clock" size="s" /> - <span className="desktop">My feed</span> - </Link> - <Link to="/pm"> - <Icon name="ei-envelope" size="s" /> - <span className="desktop">Messages</span> - </Link> - <Link to="/settings" rel="nofollow"> - <Icon name="ei-gear" size="s" /> - <span className="desktop">Settings</span> + { + visitor ? + <> + <div id="ctitle"> + <Avatar user={visitor} /> + </div> + <Link to={{ pathname: '/post' }}> + <Icon name="ei-pencil" size="s" /> + <span className="desktop">Post</span> + </Link> + <Link to="/?show=my"> + <Icon name="ei-clock" size="s" /> + <span className="desktop">My feed</span> + </Link> + <Link to="/pm"> + <Icon name="ei-envelope" size="s" /> + <span className="desktop">Messages</span> + </Link> + <Link to="/settings" rel="nofollow"> + <Icon name="ei-gear" size="s" /> + <span className="desktop">Settings</span> + </Link> + </> : + <Link to={{ pathname: '/login' }}> + <Icon name="ei-user" size="s" /> + <span className="desktop">Login</span> </Link> - </> : - <Link to={{ pathname: '/login' }}> - <Icon name="ei-user" size="s" /> - <span className="desktop">Login</span> - </Link> } <Link to={{ pathname: '/discover' }} rel="nofollow"> <Icon name="ei-search" size="s" /> @@ -187,8 +167,8 @@ export default function App({ footer }) { <Route exact path="/" element={<Discussions />} /> <Route exact path="/home" element={<Home />} /> <Route exact path="/discover" element={<Discover />} /> - <Route exact path="/settings" element={<Settings onChange={auth} />} /> - <Route exact path="/login" element={<Login onAuth={auth} />} /> + <Route exact path="/settings" element={<Settings onChange={updateStatus} />} /> + <Route exact path="/login" element={<Login onAuth={updateStatus} />} /> <Route exact path="/post" element={<Post />} /> <Route exact path="/pm" element={<Contacts />} /> <Route exact path="/pm/:user" element={<Chat connection={eventSource} />} /> diff --git a/vnext/src/api/index.js b/vnext/src/api/index.js index 566478a9..24f2fe88 100644 --- a/vnext/src/api/index.js +++ b/vnext/src/api/index.js @@ -87,11 +87,11 @@ client.interceptors.request.use(config => { /** * fetch my info - * @param {string} username - * @param {string} password + * @param {string=} username + * @param {string=} password * @returns {Promise<SecureUser, Error>} me object */ -export function me(username = '', password = '') { +export function me(username, password) { let cookies = new Cookies() return new Promise((resolve, reject) => { client.get('/api/me', { diff --git a/vnext/src/index.js b/vnext/src/index.js index 77f152af..7959186f 100644 --- a/vnext/src/index.js +++ b/vnext/src/index.js @@ -15,27 +15,38 @@ import { CookiesProvider } from 'react-cookie' import { HelmetProvider } from 'react-helmet-async' import { VisitorProvider } from './ui/VisitorContext' +import { me } from './api' const Juick = lazy(() => import('./App')) const props = window.__PROPS__ ? JSON.parse(decodeURIComponent(escape(atob(window.__PROPS__)))) : {} -const JuickApp = () => ( - <StrictMode> - <HelmetProvider> - <VisitorProvider> - <CookiesProvider> - <BrowserRouter> - <Juick {...props} /> - </BrowserRouter> - </CookiesProvider> - </VisitorProvider> - </HelmetProvider> - </StrictMode> -) - -let root = document.getElementById('app') -if (window.__PROPS__) { - hydrateRoot(root, <JuickApp />) -} else { - createRoot(root).render(<JuickApp />) +function ready(fn) { + if (document.readyState != 'loading') { + fn() + } else { + document.addEventListener('DOMContentLoaded', fn) + } } + +ready(async () => { + let visitor = await me() + const JuickApp = () => ( + <StrictMode> + <HelmetProvider> + <VisitorProvider auth={visitor}> + <CookiesProvider> + <BrowserRouter> + <Juick {...props} /> + </BrowserRouter> + </CookiesProvider> + </VisitorProvider> + </HelmetProvider> + </StrictMode> + ) + let root = document.getElementById('app') + if (window.__PROPS__) { + hydrateRoot(root, <JuickApp />) + } else { + createRoot(root).render(<JuickApp />) + } +}) diff --git a/vnext/src/ui/Feeds.js b/vnext/src/ui/Feeds.js index bb386e5a..16b6b534 100644 --- a/vnext/src/ui/Feeds.js +++ b/vnext/src/ui/Feeds.js @@ -160,7 +160,6 @@ function Feed({ query }) { const location = useLocation() const [visitor] = useVisitor() const [state, setState] = useState({ - hash: visitor.hash, msgs: [], nextpage: null, error: false, diff --git a/vnext/src/ui/Login.js b/vnext/src/ui/Login.js index 5d9908cb..ed0e990c 100644 --- a/vnext/src/ui/Login.js +++ b/vnext/src/ui/Login.js @@ -23,8 +23,8 @@ function Login({ onAuth }) { const navigate = useNavigate() const [visitor] = useVisitor() useEffect(() => { - if (visitor.hash) { - const {retpath } = location.state || '/' + if (visitor && visitor.hash) { + const retpath = location.state?.retpath || '/' console.log(retpath) navigate(retpath) } diff --git a/vnext/src/ui/Message.js b/vnext/src/ui/Message.js index e4135700..eba0f327 100644 --- a/vnext/src/ui/Message.js +++ b/vnext/src/ui/Message.js @@ -53,7 +53,7 @@ export default function Message({ data, isThread, onToggleSubscription, children } } }, []) - const canComment = data.user && visitor.uid === data.user.uid || !data.ReadOnly && visitor.uid > 0 + const canComment = data.user && visitor && visitor.uid === data.user.uid || !data.ReadOnly && visitor && visitor.uid > 0 || !data.ReadOnly && !isThread return ( <div className="msg-cont"> @@ -70,7 +70,7 @@ export default function Message({ data, isThread, onToggleSubscription, children </time> </Link> { - visitor.uid == data.user.uid && + visitor && visitor.uid == data.user.uid && <> <span> · </span> <Link to={{ @@ -100,13 +100,13 @@ export default function Message({ data, isThread, onToggleSubscription, children <div className="embedContainer" ref={embedRef} /> {canComment && <nav className="l"> - {data.user && visitor.uid === data.user.uid ? ( + {data.user && visitor && visitor.uid === data.user.uid ? ( <Link to={`/${data.user.uname}/${data.mid}`} className="a-like msg-button" state={{ data: data }}> <Icon name="ei-heart" size="s" /> <span>{likesSummary}</span> </Link> - ) : visitor.uid > 0 ? ( + ) : visitor && visitor.uid > 0 ? ( <Link to={'/post'} className="a-like msg-button"> <Icon name="ei-heart" size="s" /> <span>{likesSummary}</span> diff --git a/vnext/src/ui/VisitorContext.js b/vnext/src/ui/VisitorContext.js index 9740f9ca..a95090e5 100644 --- a/vnext/src/ui/VisitorContext.js +++ b/vnext/src/ui/VisitorContext.js @@ -2,23 +2,20 @@ import { createContext, useContext, useState } from 'react' const Visitor = createContext() -/** @type {import('../api').SecureUser} */ -const unknownUser = { - uid: -1 -} - /** - * @param { import('react').PropsWithChildren<{}> } props + * @param { import('react').PropsWithChildren<{}> & { + * auth?: import('../api').SecureUser + * }} props */ -export function VisitorProvider({ children }) { - const state = useState(unknownUser) +export function VisitorProvider({ auth, children }) { + const state = useState(auth) return <Visitor.Provider value={state}>{children}</Visitor.Provider> } /** * Visitor hook * @returns {[ - * import('../api').SecureUser, + * (import('../api').SecureUser|undefined), * import('react').Dispatch<import('react').SetStateAction<import('../api').SecureUser>> * ]} visitor hook */ @@ -28,4 +25,4 @@ export function useVisitor() { throw new Error('useVisitor must be used within a VisitorProvider') } return visitor -}
\ No newline at end of file +} |