diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 54c13172..6543b24d 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -86,10 +86,10 @@ const getTitleAndSubtitle = ( export const ArticleCard = (props: ArticleCardProps) => { const { t, lang, formatDate } = useLocalize() const { author } = useSession() - const mainTopicSlug = props.article.main_topic + const mainTopicSlug = props.article.main_topic || '' const mainTopic = props.article.topics.find((tpc: Topic) => tpc.slug === mainTopicSlug) const mainTopicTitle = - lang() === 'ru' && mainTopic?.title ? mainTopic.title : mainTopicSlug.replace('-', ' ') + mainTopicSlug && lang() === 'en' ? mainTopicSlug.replace('-', ' ') : mainTopic.title const formattedDate = createMemo(() => { return formatDate(new Date(props.article.created_at * 1000)) diff --git a/src/components/Nav/AuthModal/AuthModal.module.scss b/src/components/Nav/AuthModal/AuthModal.module.scss index 1727fef6..e596c41f 100644 --- a/src/components/Nav/AuthModal/AuthModal.module.scss +++ b/src/components/Nav/AuthModal/AuthModal.module.scss @@ -40,8 +40,8 @@ .authImage { @include font-size(1.5rem); - background: var(--background-color-invert) url('https://cdn.discours.io/production/image/auth-page.jpg') - center no-repeat; + background: var(--background-color-invert) + url('https://images.discours.io/unsafe/1600x/production/image/auth-page.jpg') center no-repeat; background-size: cover; color: var(--default-color-invert); display: flex; diff --git a/src/components/Nav/AuthModal/EmailConfirm.tsx b/src/components/Nav/AuthModal/EmailConfirm.tsx index 12e14acb..ab23280a 100644 --- a/src/components/Nav/AuthModal/EmailConfirm.tsx +++ b/src/components/Nav/AuthModal/EmailConfirm.tsx @@ -1,7 +1,7 @@ import type { ConfirmEmailSearchParams } from './types' import { clsx } from 'clsx' -import { createMemo, createSignal, onMount, Show } from 'solid-js' +import { createEffect, createMemo, createSignal, onMount, Show } from 'solid-js' import { useLocalize } from '../../../context/localize' import { useSession } from '../../../context/session' @@ -17,7 +17,9 @@ export const EmailConfirm = () => { actions: { confirmEmail, loadSession, loadAuthor }, session, } = useSession() - const confirmedEmail = createMemo(() => session()?.user?.email_verified) + const [confirmedEmail, setConfirmedEmail] = createSignal( + Boolean(session()?.user?.email_verified), + ) const [isTokenExpired, setIsTokenExpired] = createSignal(false) const [isTokenInvalid, setIsTokenInvalid] = createSignal(false) @@ -29,6 +31,7 @@ export const EmailConfirm = () => { try { await confirmEmail({ token }) await loadSession() + changeSearchParam({}) await loadAuthor() } catch (error) { if (error instanceof ApiError) { @@ -48,6 +51,8 @@ export const EmailConfirm = () => { } }) + createEffect(() => setConfirmedEmail(session()?.user?.email_verified)) + return (
{/* TODO: texts */} diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 9c927eec..c85909cb 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -81,11 +81,11 @@ export const AuthorView = (props: Props) => { await loadMore() } const { authors, topics } = await fetchSubscriptions() - setFollowing([...authors, ...topics]) + setFollowing([...(authors || []), ...(topics || [])]) }) - onMount(() => { - document.title = author().name + createEffect(() => { + document.title = author()?.name }) const loadMore = async () => { @@ -115,7 +115,7 @@ export const AuthorView = (props: Props) => { const [commented, setCommented] = createSignal([]) createEffect(async () => { - if (getPage().route === 'authorComments') { + if (getPage().route === 'authorComments' && props.author) { try { const data = await apiClient.getReactionsBy({ by: { comment: true, created_by: props.author.id }, diff --git a/src/components/Views/DraftsView/DraftsView.tsx b/src/components/Views/DraftsView/DraftsView.tsx index 1ab7f213..f7da3fbf 100644 --- a/src/components/Views/DraftsView/DraftsView.tsx +++ b/src/components/Views/DraftsView/DraftsView.tsx @@ -18,7 +18,8 @@ export const DraftsView = () => { const loadDrafts = async () => { const loadedDrafts = await apiClient.getDrafts() - setDrafts(loadedDrafts.reverse()) + if (loadedDrafts) setDrafts(loadedDrafts.reverse()) + else setDrafts([]) } onMount(() => { diff --git a/src/context/connect.tsx b/src/context/connect.tsx index c243cfd7..0695b5a0 100644 --- a/src/context/connect.tsx +++ b/src/context/connect.tsx @@ -28,10 +28,8 @@ const ConnectContext = createContext() export const ConnectProvider = (props: { children: JSX.Element }) => { const [messageHandlers, setHandlers] = createSignal>([]) // const [messages, setMessages] = createSignal>([]); - const [connected, setConnected] = createSignal(false) const { - isAuthenticated, actions: { getToken }, } = useSession() @@ -41,50 +39,42 @@ export const ConnectProvider = (props: { children: JSX.Element }) => { const [retried, setRetried] = createSignal(0) createEffect(async () => { - if (isAuthenticated() && !connected()) { - const token = getToken() - if (token) { - await fetchEventSource('https://connect.discours.io', { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - Authorization: token, - }, - onmessage(event) { - const m: SSEMessage = JSON.parse(event.data) - console.log('[context.connect] Received message:', m) + const token = getToken() + if (token && !connected()) { + await fetchEventSource('https://connect.discours.io', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: token, + }, + onmessage(event) { + const m: SSEMessage = JSON.parse(event.data) + console.log('[context.connect] Received message:', m) - // Iterate over all registered handlers and call them - messageHandlers().forEach((handler) => handler(m)) - }, - async onopen(response) { - console.log('[context.connect] SSE connection opened', response) - if (response.ok && response.headers.get('content-type') === EventStreamContentType) { - setConnected(true) - return - } else if (response.status === 401) { - throw new Error('unauthorized') - } else { - setRetried((r) => r + 1) - throw new Error() - } - }, - onclose() { - console.log('[context.connect] SSE connection closed by server') - setConnected(false) - }, - onerror(err) { - if (err.message == 'unauthorized' || retried() > RECONNECT_TIMES) { - throw err // rethrow to stop the operation - } else { - // do nothing to automatically retry. You can also - // return a specific retry interval here. - } - }, - }) - - return - } + // Iterate over all registered handlers and call them + messageHandlers().forEach((handler) => handler(m)) + }, + async onopen(response) { + console.log('[context.connect] SSE connection opened', response) + if (response.ok && response.headers.get('content-type') === EventStreamContentType) { + setConnected(true) + } else if (response.status === 401) { + throw new Error('unauthorized') + } else { + setRetried((r) => r + 1) + throw new Error('Internal Error') + } + }, + onclose() { + console.log('[context.connect] SSE connection closed by server') + setConnected(false) + }, + onerror(err) { + if (err.message === 'unauthorized' || retried() > RECONNECT_TIMES) { + throw err // rethrow to stop the operation + } + }, + }) } }) diff --git a/src/context/inbox.tsx b/src/context/inbox.tsx index e2a74520..e963eb54 100644 --- a/src/context/inbox.tsx +++ b/src/context/inbox.tsx @@ -62,7 +62,7 @@ export const InboxProvider = (props: { children: JSX.Element }) => { setChats(newChats) } } catch (error) { - console.log('[loadChats] error: ', error) + console.log('[loadChats] error:', error) } } diff --git a/src/context/notifications.tsx b/src/context/notifications.tsx index a41d77c1..9dbd05ac 100644 --- a/src/context/notifications.tsx +++ b/src/context/notifications.tsx @@ -1,6 +1,6 @@ import type { Accessor, JSX } from 'solid-js' -import { createContext, createEffect, createMemo, createSignal, onMount, useContext } from 'solid-js' +import { createContext, createMemo, createSignal, onMount, useContext } from 'solid-js' import { createStore } from 'solid-js/store' import { Portal } from 'solid-js/web' diff --git a/src/context/session.tsx b/src/context/session.tsx index da3e07bb..7b80dd6c 100644 --- a/src/context/session.tsx +++ b/src/context/session.tsx @@ -6,7 +6,6 @@ import { VerifyEmailInput, LoginInput, AuthToken, - User, Authorizer, ConfigType, } from '@authorizerdev/authorizer-js' @@ -22,11 +21,11 @@ import { } from 'solid-js' import { apiClient } from '../graphql/client/core' +import { useRouter } from '../stores/router' import { showModal } from '../stores/ui' import { useLocalize } from './localize' import { useSnackbar } from './snackbar' -import { useRouter } from '../stores/router' const config: ConfigType = { authorizerURL: 'https://auth.discours.io', @@ -86,13 +85,13 @@ export const SessionProvider = (props: { const getSession = async (): Promise => { try { const tkn = getToken() - console.debug('[context.session] token before: ', tkn) + console.debug('[context.session] token before:', tkn) const authResult = await authorizer().getSession({ Authorization: tkn, }) if (authResult?.access_token) { mutate(authResult) - console.debug('[context.session] token after: ', authResult.access_token) + console.debug('[context.session] token after:', authResult.access_token) await loadSubscriptions() return authResult } @@ -112,8 +111,6 @@ export const SessionProvider = (props: { initialValue: null, }) - const user = createMemo(() => session()?.user) - createEffect(() => { // detect confirm redirect const params = searchParams() @@ -196,10 +193,10 @@ export const SessionProvider = (props: { setConfig({ ...config, ...metaRes, redirectURL: window.location.origin + '/?modal=auth' }) console.log('[context.session] refreshing session...') const s = await getSession() - console.debug('[context.session] session: ', s) + console.debug('[context.session] session:', s) console.log('[context.session] loading author...') const a = await loadAuthor() - console.debug('[context.session] author: ', a) + console.debug('[context.session] author:', a) setIsSessionLoaded(true) console.log('[context.session] loaded') }) @@ -224,7 +221,7 @@ export const SessionProvider = (props: { } const confirmEmail = async (input: VerifyEmailInput) => { - console.log(`[context.session] calling authorizer's verify email with ${input}`) + console.debug(`[context.session] calling authorizer's verify email with`, input) const at: void | AuthToken = await authorizer().verifyEmail(input) if (at) mutate(at) console.log(`[context.session] confirmEmail got result ${at}`)