This commit is contained in:
Ren Amamiya
2023-03-24 10:59:28 +07:00
parent 18a9bf3e49
commit 47f6e6833b
32 changed files with 419 additions and 524 deletions

View File

@@ -1,70 +1,53 @@
import { DatabaseContext } from '@components/contexts/database';
import { RelayContext } from '@components/contexts/relay';
import { RelayContext } from '@components/relaysProvider';
import { activeAccountAtom } from '@stores/account';
import { hasNewerNoteAtom } from '@stores/note';
import { relaysAtom } from '@stores/relays';
import { dateToUnix, hoursAgo } from '@utils/getDate';
import { createCacheNote, getAllFollowsByID } from '@utils/storage';
import { useLocalStorage } from '@rehooks/local-storage';
import { useSetAtom } from 'jotai';
import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { useAtom, useSetAtom } from 'jotai';
import { memo, useContext, useEffect, useRef, useState } from 'react';
export const NoteConnector = memo(function NoteConnector() {
const { db }: any = useContext(DatabaseContext);
const relayPool: any = useContext(RelayContext);
const [follows]: any = useLocalStorage('follows');
const [relays]: any = useLocalStorage('relays');
const pool: any = useContext(RelayContext);
const setHasNewerNote = useSetAtom(hasNewerNoteAtom);
const [isOnline, setIsOnline] = useState(navigator.onLine);
const [relays] = useAtom(relaysAtom);
const [activeAccount] = useAtom(activeAccountAtom);
const [isOnline] = useState(navigator.onLine);
const now = useRef(new Date());
const insertDB = useCallback(
async (event: any) => {
// insert to local database
await db.execute(
'INSERT OR IGNORE INTO cache_notes (id, pubkey, created_at, kind, content, tags) VALUES (?, ?, ?, ?, ?, ?);',
[event.id, event.pubkey, event.created_at, event.kind, event.content, JSON.stringify(event.tags)]
);
},
[db]
);
useMemo(() => {
relayPool.subscribe(
[
{
kinds: [1],
authors: follows,
since: dateToUnix(hoursAgo(12, now.current)),
},
],
relays,
(event: any) => {
// insert event to local database
insertDB(event).catch(console.error);
// ask user load newer note
if (event.created_at > dateToUnix(now.current)) {
setHasNewerNote(true);
}
}
);
}, [relayPool, follows, relays, insertDB, setHasNewerNote]);
useEffect(() => {
const handleStatusChange = () => {
setIsOnline(navigator.onLine);
};
let unsubscribe;
window.addEventListener('online', handleStatusChange);
window.addEventListener('offline', handleStatusChange);
getAllFollowsByID(activeAccount.id).then((follows) => {
unsubscribe = pool.subscribe(
[
{
kinds: [1],
authors: follows,
since: dateToUnix(hoursAgo(12, now.current)),
},
],
relays,
(event: any) => {
// insert event to local database
createCacheNote(event);
// ask user load newer note
if (event.created_at > dateToUnix(now.current)) {
setHasNewerNote(true);
}
}
);
});
return () => {
window.removeEventListener('online', handleStatusChange);
window.removeEventListener('offline', handleStatusChange);
unsubscribe();
};
}, [isOnline]);
}, [activeAccount.id, pool, relays, setHasNewerNote]);
return (
<>

View File

@@ -1,8 +1,10 @@
import { RelayContext } from '@components/contexts/relay';
import { CommentsCounter } from '@components/note/counter/comments';
import { LikesCounter } from '@components/note/counter/likes';
import { RelayContext } from '@components/relaysProvider';
import { useLocalStorage } from '@rehooks/local-storage';
import { relaysAtom } from '@stores/relays';
import { useAtom } from 'jotai';
import { useContext, useEffect, useState } from 'react';
export default function NoteMetadata({
@@ -16,14 +18,14 @@ export default function NoteMetadata({
eventTime: string;
eventContent: any;
}) {
const relayPool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const pool: any = useContext(RelayContext);
const [relays] = useAtom(relaysAtom);
const [likes, setLikes] = useState(0);
const [comments, setComments] = useState(0);
useEffect(() => {
const unsubscribe = relayPool.subscribe(
const unsubscribe = pool.subscribe(
[
{
'#e': [eventID],
@@ -56,7 +58,7 @@ export default function NoteMetadata({
return () => {
unsubscribe();
};
}, [eventID, relayPool, relays]);
}, [eventID, pool, relays]);
return (
<div className="relative z-10 -ml-1 flex items-center gap-8">

View File

@@ -1,14 +1,17 @@
import { RelayContext } from '@components/contexts/relay';
import { ImageWithFallback } from '@components/imageWithFallback';
import { RelayContext } from '@components/relaysProvider';
import { UserExtend } from '@components/user/extend';
import { activeAccountAtom } from '@stores/account';
import { relaysAtom } from '@stores/relays';
import { dateToUnix } from '@utils/getDate';
import CommentIcon from '@assets/icons/comment';
import * as Dialog from '@radix-ui/react-dialog';
import { SizeIcon } from '@radix-ui/react-icons';
import useLocalStorage from '@rehooks/local-storage';
import { useAtom } from 'jotai';
import { useRouter } from 'next/router';
import { getEventHash, signEvent } from 'nostr-tools';
import { memo, useContext, useState } from 'react';
@@ -27,15 +30,15 @@ export const CommentsCounter = memo(function CommentsCounter({
eventContent: any;
}) {
const router = useRouter();
const relayPool: any = useContext(RelayContext);
const pool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const [currentUser]: any = useLocalStorage('current-user');
const [relays] = useAtom(relaysAtom);
const [activeAccount] = useAtom(activeAccountAtom);
const [open, setOpen] = useState(false);
const [value, setValue] = useState('');
const profile = JSON.parse(currentUser.metadata);
const profile = JSON.parse(activeAccount.metadata);
const openThread = () => {
router.push(`/newsfeed/${eventID}`);
@@ -46,13 +49,13 @@ export const CommentsCounter = memo(function CommentsCounter({
content: value,
created_at: dateToUnix(),
kind: 1,
pubkey: currentUser.id,
pubkey: activeAccount.id,
tags: [['e', eventID]],
};
event.id = getEventHash(event);
event.sig = signEvent(event, currentUser.privkey);
event.sig = signEvent(event, activeAccount.privkey);
relayPool.publish(event, relays);
pool.publish(event, relays);
setOpen(false);
};

View File

@@ -1,11 +1,14 @@
import { RelayContext } from '@components/contexts/relay';
import { RelayContext } from '@components/relaysProvider';
import { activeAccountAtom } from '@stores/account';
import { relaysAtom } from '@stores/relays';
import { dateToUnix } from '@utils/getDate';
import LikeIcon from '@assets/icons/like';
import LikedIcon from '@assets/icons/liked';
import { useLocalStorage } from '@rehooks/local-storage';
import { useAtom } from 'jotai';
import { getEventHash, signEvent } from 'nostr-tools';
import { memo, useContext, useEffect, useState } from 'react';
@@ -18,10 +21,10 @@ export const LikesCounter = memo(function LikesCounter({
eventID: string;
eventPubkey: string;
}) {
const relayPool: any = useContext(RelayContext);
const pool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const [currentUser]: any = useLocalStorage('current-user');
const [relays] = useAtom(relaysAtom);
const [activeAccount] = useAtom(activeAccountAtom);
const [isReact, setIsReact] = useState(false);
const [like, setLike] = useState(0);
@@ -37,12 +40,12 @@ export const LikesCounter = memo(function LikesCounter({
['p', eventPubkey],
],
created_at: dateToUnix(),
pubkey: currentUser.id,
pubkey: activeAccount.id,
};
event.id = getEventHash(event);
event.sig = signEvent(event, currentUser.privkey);
event.sig = signEvent(event, activeAccount.privkey);
// publish event to all relays
relayPool.publish(event, relays);
pool.publish(event, relays);
// update state to change icon to filled heart
setIsReact(true);
// update counter

View File

@@ -1,11 +1,14 @@
import { RelayContext } from '@components/contexts/relay';
import { RelayContext } from '@components/relaysProvider';
import { activeAccountAtom } from '@stores/account';
import { relaysAtom } from '@stores/relays';
import { dateToUnix } from '@utils/getDate';
import * as Dialog from '@radix-ui/react-dialog';
import { SizeIcon } from '@radix-ui/react-icons';
import { useLocalStorage } from '@rehooks/local-storage';
import * as commands from '@uiw/react-md-editor/lib/commands';
import { useAtom } from 'jotai';
import dynamic from 'next/dynamic';
import { getEventHash, signEvent } from 'nostr-tools';
import { useContext, useState } from 'react';
@@ -15,16 +18,16 @@ const MDEditor = dynamic(() => import('@uiw/react-md-editor').then((mod) => mod.
});
export default function FormBasic() {
const relayPool: any = useContext(RelayContext);
const pool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const [currentUser]: any = useLocalStorage('current-user');
const [relays] = useAtom(relaysAtom);
const [activeAccount] = useAtom(activeAccountAtom);
const [open, setOpen] = useState(false);
const [value, setValue] = useState('');
const pubkey = currentUser.id;
const privkey = currentUser.privkey;
const pubkey = activeAccount.id;
const privkey = activeAccount.privkey;
const submitEvent = () => {
const event: any = {
@@ -37,7 +40,7 @@ export default function FormBasic() {
event.id = getEventHash(event);
event.sig = signEvent(event, privkey);
relayPool.publish(event, relays);
pool.publish(event, relays);
setValue('');
};

View File

@@ -1,33 +1,36 @@
import { RelayContext } from '@components/contexts/relay';
import { ImageWithFallback } from '@components/imageWithFallback';
import { RelayContext } from '@components/relaysProvider';
import { activeAccountAtom } from '@stores/account';
import { relaysAtom } from '@stores/relays';
import { dateToUnix } from '@utils/getDate';
import { useLocalStorage } from '@rehooks/local-storage';
import { useAtom } from 'jotai';
import { getEventHash, signEvent } from 'nostr-tools';
import { useContext, useState } from 'react';
export default function FormComment({ eventID }: { eventID: any }) {
const relayPool: any = useContext(RelayContext);
const pool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const [currentUser]: any = useLocalStorage('current-user');
const [relays] = useAtom(relaysAtom);
const [activeAccount] = useAtom(activeAccountAtom);
const [value, setValue] = useState('');
const profile = JSON.parse(currentUser.metadata);
const profile = JSON.parse(activeAccount.metadata);
const submitEvent = () => {
const event: any = {
content: value,
created_at: dateToUnix(),
kind: 1,
pubkey: currentUser.id,
pubkey: activeAccount.id,
tags: [['e', eventID]],
};
event.id = getEventHash(event);
event.sig = signEvent(event, currentUser.privkey);
event.sig = signEvent(event, activeAccount.privkey);
relayPool.publish(event, relays);
pool.publish(event, relays);
};
return (
@@ -37,7 +40,7 @@ export default function FormComment({ eventID }: { eventID: any }) {
<div className="relative h-11 w-11 shrink-0 overflow-hidden rounded-md border border-white/10">
<ImageWithFallback
src={profile.picture}
alt={currentUser.id}
alt={activeAccount.id}
fill={true}
className="rounded-md object-cover"
/>

View File

@@ -1,35 +1,21 @@
import { DatabaseContext } from '@components/contexts/database';
import { RelayContext } from '@components/contexts/relay';
import { Content } from '@components/note/content';
import { RelayContext } from '@components/relaysProvider';
import useLocalStorage from '@rehooks/local-storage';
import { relaysAtom } from '@stores/relays';
import { createCacheNote, getNoteByID } from '@utils/storage';
import { useAtom } from 'jotai';
import { memo, useCallback, useContext, useEffect, useState } from 'react';
export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
const { db }: any = useContext(DatabaseContext);
const relayPool: any = useContext(RelayContext);
const pool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const [relays] = useAtom(relaysAtom);
const [event, setEvent] = useState(null);
const insertDB = useCallback(
async (event: any) => {
// insert to local database
await db.execute(
'INSERT OR IGNORE INTO cache_notes (id, pubkey, created_at, kind, content, tags, is_root) VALUES (?, ?, ?, ?, ?, ?, ?);',
[event.id, event.pubkey, event.created_at, event.kind, event.content, JSON.stringify(event.tags), 0]
);
},
[db]
);
const getData = useCallback(async () => {
const result = await db.select(`SELECT * FROM cache_notes WHERE id = "${id}"`);
return result[0];
}, [db, id]);
const fetchEvent = useCallback(() => {
relayPool.subscribe(
pool.subscribe(
[
{
ids: [id],
@@ -41,7 +27,7 @@ export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
// update state
setEvent(event);
// insert to database
insertDB(event);
createCacheNote(event);
},
undefined,
undefined,
@@ -49,19 +35,17 @@ export const MentionNote = memo(function MentionNote({ id }: { id: string }) {
unsubscribeOnEose: true,
}
);
}, [id, insertDB, relayPool, relays]);
}, [id, pool, relays]);
useEffect(() => {
getData()
.then((res) => {
if (res) {
setEvent(res);
} else {
fetchEvent();
}
})
.catch(console.error);
}, [fetchEvent, getData]);
getNoteByID(id).then((res) => {
if (res) {
setEvent(res);
} else {
fetchEvent();
}
});
}, [fetchEvent, id]);
if (event) {
return (

View File

@@ -1,35 +1,21 @@
import { DatabaseContext } from '@components/contexts/database';
import { RelayContext } from '@components/contexts/relay';
import { Content } from '@components/note/content';
import { RelayContext } from '@components/relaysProvider';
import useLocalStorage from '@rehooks/local-storage';
import { relaysAtom } from '@stores/relays';
import { createCacheNote, getNoteByID } from '@utils/storage';
import { useAtom } from 'jotai';
import { memo, useCallback, useContext, useEffect, useState } from 'react';
export const RootNote = memo(function RootNote({ id }: { id: string }) {
const { db }: any = useContext(DatabaseContext);
const relayPool: any = useContext(RelayContext);
const pool: any = useContext(RelayContext);
const [relays]: any = useLocalStorage('relays');
const [relays] = useAtom(relaysAtom);
const [event, setEvent] = useState(null);
const insertDB = useCallback(
async (event: any) => {
// insert to local database
await db.execute(
'INSERT OR IGNORE INTO cache_notes (id, pubkey, created_at, kind, content, tags, is_root) VALUES (?, ?, ?, ?, ?, ?, ?);',
[event.id, event.pubkey, event.created_at, event.kind, event.content, JSON.stringify(event.tags), 1]
);
},
[db]
);
const getData = useCallback(async () => {
const result = await db.select(`SELECT * FROM cache_notes WHERE id = "${id}"`);
return result[0];
}, [db, id]);
const fetchEvent = useCallback(() => {
relayPool.subscribe(
pool.subscribe(
[
{
ids: [id],
@@ -41,7 +27,7 @@ export const RootNote = memo(function RootNote({ id }: { id: string }) {
// update state
setEvent(event);
// insert to database
insertDB(event);
createCacheNote(event);
},
undefined,
undefined,
@@ -49,19 +35,17 @@ export const RootNote = memo(function RootNote({ id }: { id: string }) {
unsubscribeOnEose: true,
}
);
}, [id, insertDB, relayPool, relays]);
}, [id, pool, relays]);
useEffect(() => {
getData()
.then((res) => {
if (res) {
setEvent(res);
} else {
fetchEvent();
}
})
.catch(console.error);
}, [fetchEvent, getData]);
getNoteByID(id).then((res) => {
if (res) {
setEvent(res);
} else {
fetchEvent();
}
});
}, [fetchEvent, id]);
if (event) {
return (