fixed ssr errors

This commit is contained in:
Ren Amamiya 2023-04-23 08:25:27 +07:00
parent b9bafc851e
commit 8b6bffcff2
14 changed files with 101 additions and 45 deletions

View File

@ -1,6 +1,5 @@
import { platform } from '@tauri-apps/api/os';
import { ArrowLeft, ArrowRight, Refresh } from 'iconoir-react';
import { useLayoutEffect, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
export default function AppActions() {
const [os, setOS] = useState('');
@ -17,13 +16,23 @@ export default function AppActions() {
window.location.reload();
};
useLayoutEffect(() => {
const getPlatform = async () => {
const result = await platform();
setOS(result);
};
const getPlatform = useCallback(async () => {
const { platform } = await import('@tauri-apps/api/os');
const result = await platform();
getPlatform().catch(console.error);
setOS(result);
}, []);
useEffect(() => {
let ignore = false;
if (!ignore) {
getPlatform().catch(console.error);
}
return () => {
ignore = true;
};
}, []);
return (

View File

@ -7,7 +7,7 @@ export const ChannelListItem = ({ data }: { data: any }) => {
return (
<a
href={`channel?id=${data.event_id}`}
href={`/channel?id=${data.event_id}`}
className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 hover:bg-zinc-900"
>
<div className="relative h-5 w-5 shrink-0 rounded">

View File

@ -11,7 +11,7 @@ import { useEffect, useState } from 'react';
export default function ChatList() {
const [list, setList] = useState([]);
const [activeAccount]: any = useLocalStorage('account', {});
const profile = JSON.parse(activeAccount.metadata);
const profile = activeAccount.metadata ? JSON.parse(activeAccount.metadata) : null;
useEffect(() => {
let ignore = false;

View File

@ -13,7 +13,7 @@ import { useCallback, useContext, useEffect, useRef } from 'react';
export default function EventCollector() {
const [pool, relays]: any = useContext(RelayContext);
const [activeAccount]: any = useLocalStorage('account', {});
const [activeAccount]: any = useLocalStorage('account', null);
const setHasNewerNote = useSetAtom(hasNewerNoteAtom);
const follows = JSON.parse(activeAccount.follows);
@ -106,7 +106,15 @@ export default function EventCollector() {
}, [activeAccount.pubkey, activeAccount.id, follows, pool, relays, setHasNewerNote]);
useEffect(() => {
subscribe();
let ignore = false;
if (!ignore) {
subscribe();
}
return () => {
ignore = true;
};
}, [setHasNewerNote, subscribe]);
return <NetworkStatusIndicator />;

View File

@ -1,5 +1,5 @@
import { memo } from 'react';
import ReactPlayer from 'react-player/lazy';
import ReactPlayer from 'react-player';
export const VideoPreview = memo(function VideoPreview({ url }: { url: string }) {
return (

View File

@ -18,7 +18,7 @@ import LumeSymbol from '@assets/icons/Lume';
import { writeStorage } from '@rehooks/local-storage';
import { useCallback, useContext, useEffect, useRef } from 'react';
import { navigate } from 'vite-plugin-ssr/client/router';
import { navigate, prefetch } from 'vite-plugin-ssr/client/router';
export function Page() {
const [pool, relays]: any = useContext(RelayContext);
@ -123,7 +123,8 @@ export function Page() {
() => {
updateLastLogin(dateToUnix(now.current));
timeout.current = setTimeout(() => {
navigate('/newsfeed/following', { overwriteLastHistoryEntry: true });
prefetch('/newsfeed/following');
navigate('/newsfeed/following');
}, 5000);
},
{
@ -152,6 +153,7 @@ export function Page() {
// fetch data
fetchData(account, account.follows);
} else {
prefetch('/onboarding');
navigate('/onboarding', { overwriteLastHistoryEntry: true });
}
})

View File

@ -10,20 +10,22 @@ import { createAccount, createPleb, updateAccount } from '@utils/storage';
import { nip02ToArray } from '@utils/transform';
import { getPublicKey } from 'nostr-tools';
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { navigate } from 'vite-plugin-ssr/client/router';
export function Page() {
const pageContext = usePageContext();
const searchParams = pageContext.urlParsed.search;
const privkey = searchParams.privkey;
const pubkey = getPublicKey(privkey);
const pubkey = useMemo(() => getPublicKey(privkey), [privkey]);
const [pool, relays]: any = useContext(RelayContext);
const [profile, setProfile] = useState({ metadata: null });
const [done, setDone] = useState(false);
const timeout = useRef(null);
const nip02 = useRef(null);
const createPlebs = useCallback(async (tags: string[]) => {
for (const tag of tags) {
@ -33,6 +35,16 @@ export function Page() {
}
}, []);
const submit = () => {
// update account's folllows with NIP-02 tag list
const arr = nip02ToArray(nip02.current);
updateAccount('follows', arr, pubkey);
// create plebs (saved nostr profile)
createPlebs(nip02.current);
// redirect to splashscreen
navigate('/', { overwriteLastHistoryEntry: true });
};
useEffect(() => {
const unsubscribe = pool.subscribe(
[
@ -43,20 +55,20 @@ export function Page() {
],
relays,
(event: any) => {
if (event.kind === 0) {
// create account
createAccount(pubkey, privkey, event.content);
// update state
setProfile({
metadata: JSON.parse(event.content),
});
} else {
if (event.tags.length > 0) {
createPlebs(event.tags);
const arr = nip02ToArray(event.tags);
// update account's folllows with NIP-02 tag list
updateAccount('follows', arr, pubkey);
}
switch (event.kind) {
case 0:
// create account
createAccount(pubkey, privkey, event.content);
// update state
setProfile({
metadata: JSON.parse(event.content),
});
break;
case 3:
nip02.current = event.tags;
break;
default:
break;
}
},
undefined,
@ -73,7 +85,7 @@ export function Page() {
unsubscribe();
clearTimeout(timeout.current);
};
}, [pool, relays, pubkey, privkey, createPlebs]);
}, [pool, relays, pubkey, privkey]);
return (
<OnboardingLayout>
@ -128,12 +140,12 @@ export function Page() {
></path>
</svg>
) : (
<a
href="/"
<button
onClick={() => submit()}
className="inline-flex w-full transform items-center justify-center rounded-lg bg-gradient-to-r from-fuchsia-300 via-orange-100 to-amber-300 px-3.5 py-2.5 font-medium text-zinc-800 active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30"
>
<span className="drop-shadow-lg">Done! Go to newsfeed</span>
</a>
</button>
)}
</div>
</div>

View File

@ -2,19 +2,31 @@ import '@renderer/index.css';
import { Shell } from '@renderer/shell';
import { PageContextClient } from '@renderer/types';
import { hydrateRoot } from 'react-dom/client';
import { Root, createRoot, hydrateRoot } from 'react-dom/client';
export const clientRouting = true;
let root: Root;
export async function render(pageContext: PageContextClient) {
const { Page, pageProps } = pageContext;
if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined');
hydrateRoot(
document.getElementById('app')!,
const page = (
<Shell pageContext={pageContext}>
<Page {...pageProps} />
</Shell>
);
const container = document.getElementById('app');
// SPA
if (container.innerHTML === '' || !pageContext.isHydration) {
if (!root) {
root = createRoot(container);
}
root.render(page);
// SSR
} else {
root = hydrateRoot(container, page);
}
}

View File

@ -7,15 +7,22 @@ import { dangerouslySkipEscape, escapeInject } from 'vite-plugin-ssr/server';
export const passToClient = ['pageProps'];
export function render(pageContext: PageContextServer) {
const { Page, pageProps } = pageContext;
let pageHtml: string;
if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined');
if (!pageContext.Page) {
// SPA
pageHtml = '';
} else {
// SSR / HTML-only
const { Page, pageProps } = pageContext;
if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined');
const pageHtml = ReactDOMServer.renderToString(
<Shell pageContext={pageContext}>
<Page {...pageProps} />
</Shell>
);
pageHtml = ReactDOMServer.renderToString(
<Shell pageContext={pageContext}>
<Page {...pageProps} />
</Shell>
);
}
return escapeInject`<!DOCTYPE html>
<html lang="en" class="dark">

View File

@ -6,6 +6,7 @@ export const nip02ToArray = (tags: string[]) => {
tags.forEach((item) => {
arr.push(item[1]);
});
return arr;
};

View File

@ -5,4 +5,9 @@ import viteTsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [react(), ssr({ prerender: true }), viteTsconfigPaths()],
define: {
global: {
window: {},
},
},
});