aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2023-10-08 18:45:33 +0300
committerGravatar Vitaly Takmazov2023-10-08 18:47:14 +0300
commitf3ec3b0b88a43e2a48db51b81f9b5778ade11248 (patch)
tree084940cccbbded3dff9d1deb0048ae09cb1bba75
parente8744a1620d7761cf721f1cc21562ad2c6ec8e5c (diff)
Fix initial auth from cookie
-rw-r--r--vnext/src/App.js84
-rw-r--r--vnext/src/api/index.js6
-rw-r--r--vnext/src/index.js49
-rw-r--r--vnext/src/ui/Feeds.js1
-rw-r--r--vnext/src/ui/Login.js4
-rw-r--r--vnext/src/ui/Message.js8
-rw-r--r--vnext/src/ui/VisitorContext.js17
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>&nbsp;&middot;&nbsp;</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
+}