This commit is contained in:
Ren Amamiya
2023-03-25 17:21:41 +07:00
parent f1647fd857
commit 17bcaa1a48
9 changed files with 163 additions and 143 deletions

View File

@@ -2,6 +2,7 @@ import NoteMetadata from '@components/note/metadata';
import { NoteParent } from '@components/note/parent';
import { ImagePreview } from '@components/note/preview/image';
import { VideoPreview } from '@components/note/preview/video';
import { NoteRepost } from '@components/note/repost';
import { UserExtend } from '@components/user/extend';
import { UserMention } from '@components/user/mention';
@@ -11,8 +12,6 @@ import { memo, useMemo } from 'react';
import ReactPlayer from 'react-player/lazy';
import reactStringReplace from 'react-string-replace';
import { NoteRepost } from './repost';
export const NoteBase = memo(function NoteBase({ event }: { event: any }) {
const router = useRouter();

View File

@@ -1,6 +1,7 @@
import NoteMetadata from '@components/note/metadata';
import { ImagePreview } from '@components/note/preview/image';
import { VideoPreview } from '@components/note/preview/video';
import { NoteRepost } from '@components/note/repost';
import { RelayContext } from '@components/relaysProvider';
import { UserExtend } from '@components/user/extend';
import { UserMention } from '@components/user/mention';
@@ -89,7 +90,7 @@ export const NoteParent = memo(function NoteParent({ id }: { id: string }) {
return <UserMention key={match + i} pubkey={tags[match][1]} />;
} else if (tags[match][0] === 'e') {
// note-mentions
return <p key={match + i}>note-{tags[match][1]}</p>;
return <NoteRepost key={match + i} id={tags[match][1]} />;
} else {
return;
}

View File

@@ -2,7 +2,10 @@ import RelayProvider from '@components/relaysProvider';
import { relaysAtom } from '@stores/relays';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Provider, useAtomValue } from 'jotai';
import { queryClientAtom } from 'jotai-tanstack-query';
import { useHydrateAtoms } from 'jotai/react/utils';
import type { NextPage } from 'next';
import type { AppProps } from 'next/app';
import { ReactElement, ReactNode } from 'react';
@@ -18,14 +21,25 @@ type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
const queryClient = new QueryClient();
const HydrateAtoms = ({ children }) => {
useHydrateAtoms([[queryClientAtom, queryClient]]);
return children;
};
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
// Use the layout defined at the page level, if available
const getLayout = Component.getLayout ?? ((page) => page);
const relays = useAtomValue(relaysAtom);
return (
<Provider>
<RelayProvider relays={relays}>{getLayout(<Component {...pageProps} />)}</RelayProvider>
</Provider>
<QueryClientProvider client={queryClient}>
<Provider>
<HydrateAtoms>
<RelayProvider relays={relays}>{getLayout(<Component {...pageProps} />)}</RelayProvider>
</HydrateAtoms>
</Provider>
</QueryClientProvider>
);
}

View File

@@ -3,17 +3,16 @@ import WithSidebarLayout from '@layouts/withSidebar';
import { NoteBase } from '@components/note/base';
import FormBasic from '@components/note/form/basic';
import { Placeholder } from '@components/note/placeholder';
import { hasNewerNoteAtom, notesAtom } from '@stores/note';
import { notesAtom } from '@stores/note';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useAtom } from 'jotai';
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useRef } from 'react';
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, Suspense, useRef } from 'react';
export default function Page() {
const [data]: any = useAtom(notesAtom);
const [hasNewerNote, setHasNewerNote] = useAtom(hasNewerNoteAtom);
const parentRef = useRef(null);
const virtualizer = useVirtualizer({
@@ -25,40 +24,26 @@ export default function Page() {
});
const items = virtualizer.getVirtualItems();
const loadNewest = () => {
console.log('load');
};
return (
<div ref={parentRef} className="scrollbar-hide h-full w-full overflow-y-auto" style={{ contain: 'strict' }}>
<div>
{hasNewerNote && (
<div className="absolute top-8 left-1/2 z-50 -translate-x-1/2 transform">
<button
onClick={() => loadNewest()}
className="inline-flex h-8 transform items-center justify-center gap-1 rounded-full bg-fuchsia-500 px-3 text-sm shadow-lg shadow-fuchsia-900/50 active:translate-y-1"
>
<span className="text-white drop-shadow">Load newest</span>
</button>
</div>
)}
</div>
<div>
<div className="relative">
<FormBasic />
</div>
<div>
{items.length > 0 && (
<div className="relative w-full" style={{ height: virtualizer.getTotalSize() }}>
<div className="absolute top-0 left-0 w-full" style={{ transform: `translateY(${items[0].start}px)` }}>
{items.map((virtualRow) => (
<div key={virtualRow.key} data-index={virtualRow.index} ref={virtualizer.measureElement}>
<NoteBase event={data[virtualRow.index]} />
</div>
))}
<Suspense fallback={<Placeholder />}>
<div>
{items.length > 0 && (
<div className="relative w-full" style={{ height: virtualizer.getTotalSize() }}>
<div className="absolute top-0 left-0 w-full" style={{ transform: `translateY(${items[0].start}px)` }}>
{items.map((virtualRow) => (
<div key={virtualRow.key} data-index={virtualRow.index} ref={virtualizer.measureElement}>
<NoteBase event={data[virtualRow.index]} />
</div>
))}
</div>
</div>
</div>
)}
</div>
)}
</div>
</Suspense>
</div>
);
}

View File

@@ -1,9 +1,9 @@
import { isSSR } from '@utils/ssr';
import { getActiveAccount } from '@utils/storage';
import { atom } from 'jotai';
import { atomWithCache } from 'jotai-cache';
export const activeAccountAtom = atom(async () => {
export const activeAccountAtom = atomWithCache(async () => {
const response = isSSR ? {} : await getActiveAccount();
return response;
});

View File

@@ -4,13 +4,18 @@ import { getAllNotes } from '@utils/storage';
import { atom } from 'jotai';
import { atomsWithQuery } from 'jotai-tanstack-query';
// usecase: notify user that connector has receive newer note
// notify user that connector has receive newer note
export const hasNewerNoteAtom = atom(false);
// usecase: query notes from database
// query notes from database
export const [notesAtom] = atomsWithQuery(() => ({
queryKey: ['notes'],
queryFn: async ({ queryKey: [] }) => {
const res = isSSR ? [] : await getAllNotes();
return res;
},
refetchInterval: 1000000,
refetchOnReconnect: true,
refetchOnWindowFocus: true,
refetchOnMount: true,
keepPreviousData: false,
}));

View File

@@ -1,9 +1,9 @@
import { isSSR } from '@utils/ssr';
import { getAllRelays } from '@utils/storage';
import { atom } from 'jotai';
import { atomWithCache } from 'jotai-cache';
export const relaysAtom = atom(async () => {
export const relaysAtom = atomWithCache(async () => {
const response = isSSR ? [] : await getAllRelays();
return response;
});