LFG !!!
This commit is contained in:
@@ -1,53 +1,41 @@
|
||||
import { DatabaseContext } from '@components/contexts/database';
|
||||
import { RelayContext } from '@components/contexts/relay';
|
||||
import { RelayContext } from '@components/relaysProvider';
|
||||
|
||||
import { relaysAtom } from '@stores/relays';
|
||||
|
||||
import { createFollows } from '@utils/storage';
|
||||
import { tagsToArray } from '@utils/tags';
|
||||
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
||||
import { AvatarIcon, ExitIcon, GearIcon } from '@radix-ui/react-icons';
|
||||
import useLocalStorage from '@rehooks/local-storage';
|
||||
import { useAtom } from 'jotai';
|
||||
import Image from 'next/image';
|
||||
import { useRouter } from 'next/router';
|
||||
import { memo, useCallback, useContext, useMemo } from 'react';
|
||||
import { memo, useContext, useEffect } from 'react';
|
||||
|
||||
export const ActiveAccount = memo(function ActiveAccount({ user }: { user: any }) {
|
||||
const pool: any = useContext(RelayContext);
|
||||
const [relays] = useAtom(relaysAtom);
|
||||
|
||||
const router = useRouter();
|
||||
const userData = JSON.parse(user.metadata);
|
||||
|
||||
const { db }: any = useContext(DatabaseContext);
|
||||
const relayPool: any = useContext(RelayContext);
|
||||
|
||||
const [relays]: any = useLocalStorage('relays');
|
||||
const [currentUser]: any = useLocalStorage('current-user');
|
||||
|
||||
const openProfile = () => {
|
||||
router.push(`/users/${currentUser.id}`);
|
||||
router.push(`/users/${user.pubkey}`);
|
||||
};
|
||||
|
||||
// save follows to database
|
||||
const insertFollows = useCallback(
|
||||
async (follows) => {
|
||||
follows.forEach(async (item) => {
|
||||
if (item) {
|
||||
// insert to database
|
||||
await db.execute(
|
||||
`INSERT OR IGNORE INTO follows (pubkey, account, kind) VALUES ("${item[1]}", "${currentUser.id}", "0")`
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
[db, currentUser.id]
|
||||
);
|
||||
|
||||
useMemo(() => {
|
||||
relayPool.subscribe(
|
||||
useEffect(() => {
|
||||
pool.subscribe(
|
||||
[
|
||||
{
|
||||
kinds: [3],
|
||||
authors: [currentUser.id],
|
||||
authors: [user.pubkey],
|
||||
},
|
||||
],
|
||||
relays,
|
||||
(event: any) => {
|
||||
insertFollows(event.tags);
|
||||
if (event.tags.length > 0) {
|
||||
createFollows(tagsToArray(event.tags), user.pubkey, 0);
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
@@ -55,7 +43,7 @@ export const ActiveAccount = memo(function ActiveAccount({ user }: { user: any }
|
||||
unsubscribeOnEose: true,
|
||||
}
|
||||
);
|
||||
}, [currentUser.id, insertFollows, relayPool, relays]);
|
||||
}, [pool, relays, user.pubkey]);
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root>
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
import { ActiveAccount } from '@components/columns/account/active';
|
||||
import { InactiveAccount } from '@components/columns/account/inactive';
|
||||
|
||||
import useLocalStorage from '@rehooks/local-storage';
|
||||
import { activeAccountAtom } from '@stores/account';
|
||||
|
||||
import { getAccounts } from '@utils/storage';
|
||||
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import Database from 'tauri-plugin-sql-api';
|
||||
|
||||
export default function AccountList() {
|
||||
const [currentUser]: any = useLocalStorage('current-user');
|
||||
const [activeAccount] = useAtom(activeAccountAtom);
|
||||
const [users, setUsers] = useState([]);
|
||||
|
||||
const renderAccount = useCallback(
|
||||
(user: { id: string }) => {
|
||||
if (user.id === currentUser.id) {
|
||||
if (user.id === activeAccount.id) {
|
||||
return <ActiveAccount key={user.id} user={user} />;
|
||||
} else {
|
||||
return <InactiveAccount key={user.id} user={user} />;
|
||||
}
|
||||
},
|
||||
[currentUser.id]
|
||||
[activeAccount.id]
|
||||
);
|
||||
|
||||
const getAccounts = useCallback(async () => {
|
||||
const db = await Database.load('sqlite:lume.db');
|
||||
const result: any = await db.select('SELECT * FROM accounts');
|
||||
|
||||
setUsers(result);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getAccounts().catch(console.error);
|
||||
}, [getAccounts]);
|
||||
const fetchAccount = async () => {
|
||||
const result: any = await getAccounts();
|
||||
setUsers(result);
|
||||
};
|
||||
|
||||
fetchAccount().catch(console.error);
|
||||
}, []);
|
||||
|
||||
return <>{users.map((user) => renderAccount(user))}</>;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
import { MessageList } from '@components/columns/navigator/messages/list';
|
||||
|
||||
import { activeAccountAtom } from '@stores/account';
|
||||
|
||||
import { getAllFollowsByID } from '@utils/storage';
|
||||
|
||||
import * as Collapsible from '@radix-ui/react-collapsible';
|
||||
import { TriangleUpIcon } from '@radix-ui/react-icons';
|
||||
import useLocalStorage from '@rehooks/local-storage';
|
||||
import { useState } from 'react';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function Messages() {
|
||||
const [open, setOpen] = useState(true);
|
||||
const [follows] = useLocalStorage('follows');
|
||||
const [follows, setFollows] = useState([]);
|
||||
const [activeAccount] = useAtom(activeAccountAtom);
|
||||
|
||||
useEffect(() => {
|
||||
getAllFollowsByID(activeAccount.id)
|
||||
.then((res: any) => setFollows(res))
|
||||
.catch(console.error);
|
||||
}, [activeAccount.id]);
|
||||
|
||||
return (
|
||||
<Collapsible.Root open={open} onOpenChange={setOpen}>
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import { deleteFromStorage, writeStorage } from '@rehooks/local-storage';
|
||||
import { createContext, useCallback, useEffect, useState } from 'react';
|
||||
import Database from 'tauri-plugin-sql-api';
|
||||
|
||||
export const DatabaseContext = createContext({});
|
||||
|
||||
const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null;
|
||||
|
||||
export default function DatabaseProvider({ children }: { children: React.ReactNode }) {
|
||||
const [done, setDone] = useState(false);
|
||||
|
||||
const getRelays = useCallback(async () => {
|
||||
const result: any[] = await db.select('SELECT relay_url FROM relays WHERE relay_status = "1"');
|
||||
const arr = [];
|
||||
result.forEach((item: { relay_url: string }) => {
|
||||
arr.push(item.relay_url);
|
||||
});
|
||||
// delete old item then save new item to local storage
|
||||
deleteFromStorage('relays');
|
||||
writeStorage('relays', arr);
|
||||
// return
|
||||
return;
|
||||
}, []);
|
||||
|
||||
const getAccount = useCallback(async () => {
|
||||
const result = await db.select(`SELECT * FROM accounts LIMIT 1`);
|
||||
// delete old item then save new item to local storage
|
||||
deleteFromStorage('current-user');
|
||||
if (result[0]) {
|
||||
writeStorage('current-user', result[0]);
|
||||
} else {
|
||||
writeStorage('current-user', null);
|
||||
}
|
||||
// return first record
|
||||
return result[0];
|
||||
}, []);
|
||||
|
||||
const getFollows = useCallback(async (id: string) => {
|
||||
const result: any[] = await db.select(`SELECT pubkey FROM follows WHERE account = "${id}"`);
|
||||
const arr = [];
|
||||
result.forEach((item: { pubkey: string }) => {
|
||||
arr.push(item.pubkey);
|
||||
});
|
||||
// delete old item then save new item to local storage
|
||||
deleteFromStorage('follows');
|
||||
writeStorage('follows', arr);
|
||||
// return
|
||||
return;
|
||||
}, []);
|
||||
|
||||
const clearCacheNote = useCallback(async () => {
|
||||
const result: any = await db.select('SELECT COUNT(*) AS "total" FROM cache_notes');
|
||||
if (result[0].total >= 1000) {
|
||||
await db.execute('DELETE FROM cache_notes');
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getRelays().catch(console.error);
|
||||
getAccount()
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
getFollows(res.id).catch(console.error);
|
||||
clearCacheNote().catch(console.error);
|
||||
}
|
||||
setDone(true);
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [getAccount, getFollows, clearCacheNote, getRelays]);
|
||||
|
||||
if (!done) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return <DatabaseContext.Provider value={{ db }}>{children}</DatabaseContext.Provider>;
|
||||
}
|
||||
@@ -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 (
|
||||
<>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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('');
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createContext, useMemo } from 'react';
|
||||
|
||||
export const RelayContext = createContext({});
|
||||
|
||||
export default function RelayProvider({ relays, children }: { relays: any; children: React.ReactNode }) {
|
||||
export default function RelayProvider({ relays, children }: { relays: Array<string>; children: React.ReactNode }) {
|
||||
const value = useMemo(() => new RelayPool(relays, { useEventCache: false, logSubscriptions: false }), [relays]);
|
||||
return <RelayContext.Provider value={value}>{children}</RelayContext.Provider>;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DatabaseContext } from '@components/contexts/database';
|
||||
import { ImageWithFallback } from '@components/imageWithFallback';
|
||||
|
||||
import { createCacheProfile, getCacheProfile } from '@utils/storage';
|
||||
import { truncate } from '@utils/truncate';
|
||||
|
||||
import { DotsHorizontalIcon } from '@radix-ui/react-icons';
|
||||
@@ -9,13 +9,12 @@ import Avatar from 'boring-avatars';
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { useRouter } from 'next/router';
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
export const UserExtend = memo(function UserExtend({ pubkey, time }: { pubkey: string; time: any }) {
|
||||
const router = useRouter();
|
||||
const { db }: any = useContext(DatabaseContext);
|
||||
const [profile, setProfile] = useState(null);
|
||||
|
||||
const openUserPage = (e) => {
|
||||
@@ -24,7 +23,6 @@ export const UserExtend = memo(function UserExtend({ pubkey, time }: { pubkey: s
|
||||
};
|
||||
|
||||
const fetchProfile = useCallback(async (id: string) => {
|
||||
console.log('fetch');
|
||||
const res = await fetch(`https://rbr.bio/${id}/metadata.json`, {
|
||||
method: 'GET',
|
||||
timeout: 30,
|
||||
@@ -32,34 +30,20 @@ export const UserExtend = memo(function UserExtend({ pubkey, time }: { pubkey: s
|
||||
return res.data;
|
||||
}, []);
|
||||
|
||||
const getCacheProfile = useCallback(async () => {
|
||||
const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`);
|
||||
return result[0];
|
||||
}, [db, pubkey]);
|
||||
|
||||
const insertCacheProfile = useCallback(
|
||||
async (event) => {
|
||||
// update state
|
||||
setProfile(JSON.parse(event.content));
|
||||
// insert to database
|
||||
await db.execute('INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES (?, ?);', [pubkey, event.content]);
|
||||
},
|
||||
[db, pubkey]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getCacheProfile()
|
||||
.then((res) => {
|
||||
if (res !== undefined) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res) => insertCacheProfile(res))
|
||||
.catch(console.error);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [fetchProfile, getCacheProfile, insertCacheProfile, pubkey]);
|
||||
getCacheProfile(pubkey).then((res) => {
|
||||
if (res) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res: any) => {
|
||||
setProfile(JSON.parse(res.content));
|
||||
createCacheProfile(pubkey, res.content);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
});
|
||||
}, [fetchProfile, pubkey]);
|
||||
|
||||
return (
|
||||
<div onClick={(e) => openUserPage(e)} className="group flex items-start gap-2">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DatabaseContext } from '@components/contexts/database';
|
||||
import { ImageWithFallback } from '@components/imageWithFallback';
|
||||
|
||||
import { createCacheProfile, getCacheProfile } from '@utils/storage';
|
||||
import { truncate } from '@utils/truncate';
|
||||
|
||||
import { DotsHorizontalIcon } from '@radix-ui/react-icons';
|
||||
@@ -8,14 +8,11 @@ import { fetch } from '@tauri-apps/api/http';
|
||||
import Avatar from 'boring-avatars';
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react';
|
||||
|
||||
truncate;
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
export const UserLarge = memo(function UserLarge({ pubkey, time }: { pubkey: string; time: any }) {
|
||||
const { db }: any = useContext(DatabaseContext);
|
||||
const [profile, setProfile] = useState(null);
|
||||
|
||||
const fetchProfile = useCallback(async (id: string) => {
|
||||
@@ -26,34 +23,20 @@ export const UserLarge = memo(function UserLarge({ pubkey, time }: { pubkey: str
|
||||
return res.data;
|
||||
}, []);
|
||||
|
||||
const getCacheProfile = useCallback(async () => {
|
||||
const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`);
|
||||
return result[0];
|
||||
}, [db, pubkey]);
|
||||
|
||||
const insertCacheProfile = useCallback(
|
||||
async (event) => {
|
||||
// update state
|
||||
setProfile(JSON.parse(event.content));
|
||||
// insert to database
|
||||
await db.execute('INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES (?, ?);', [pubkey, event.content]);
|
||||
},
|
||||
[db, pubkey]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getCacheProfile()
|
||||
.then((res) => {
|
||||
if (res !== undefined) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res) => insertCacheProfile(res))
|
||||
.catch(console.error);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [fetchProfile, getCacheProfile, insertCacheProfile, pubkey]);
|
||||
getCacheProfile(pubkey).then((res) => {
|
||||
if (res) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res: any) => {
|
||||
setProfile(JSON.parse(res.content));
|
||||
createCacheProfile(pubkey, res.content);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
});
|
||||
}, [fetchProfile, pubkey]);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { DatabaseContext } from '@components/contexts/database';
|
||||
|
||||
import { createCacheProfile, getCacheProfile } from '@utils/storage';
|
||||
import { truncate } from '@utils/truncate';
|
||||
|
||||
import { fetch } from '@tauri-apps/api/http';
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
export const UserMention = memo(function UserMention({ pubkey }: { pubkey: string }) {
|
||||
const { db }: any = useContext(DatabaseContext);
|
||||
const [profile, setProfile] = useState(null);
|
||||
|
||||
const fetchProfile = useCallback(async (id: string) => {
|
||||
@@ -17,34 +15,20 @@ export const UserMention = memo(function UserMention({ pubkey }: { pubkey: strin
|
||||
return res.data;
|
||||
}, []);
|
||||
|
||||
const getCacheProfile = useCallback(async () => {
|
||||
const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`);
|
||||
return result[0];
|
||||
}, [db, pubkey]);
|
||||
|
||||
const insertCacheProfile = useCallback(
|
||||
async (event) => {
|
||||
// insert to database
|
||||
await db.execute('INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES (?, ?);', [pubkey, event.content]);
|
||||
// update state
|
||||
setProfile(JSON.parse(event.content));
|
||||
},
|
||||
[db, pubkey]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getCacheProfile()
|
||||
.then((res) => {
|
||||
if (res !== undefined) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res) => insertCacheProfile(res))
|
||||
.catch(console.error);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [fetchProfile, getCacheProfile, insertCacheProfile, pubkey]);
|
||||
getCacheProfile(pubkey).then((res) => {
|
||||
if (res) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res: any) => {
|
||||
setProfile(JSON.parse(res.content));
|
||||
createCacheProfile(pubkey, res.content);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
});
|
||||
}, [fetchProfile, pubkey]);
|
||||
|
||||
return <span className="cursor-pointer text-fuchsia-500">@{profile?.name || truncate(pubkey, 16, ' .... ')}</span>;
|
||||
});
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { DatabaseContext } from '@components/contexts/database';
|
||||
import { ImageWithFallback } from '@components/imageWithFallback';
|
||||
|
||||
import { createCacheProfile, getCacheProfile } from '@utils/storage';
|
||||
import { truncate } from '@utils/truncate';
|
||||
|
||||
import { fetch } from '@tauri-apps/api/http';
|
||||
import Avatar from 'boring-avatars';
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
export const UserMini = memo(function UserMini({ pubkey }: { pubkey: string }) {
|
||||
const { db }: any = useContext(DatabaseContext);
|
||||
const [profile, setProfile] = useState(null);
|
||||
|
||||
const fetchProfile = useCallback(async (id: string) => {
|
||||
@@ -19,34 +18,20 @@ export const UserMini = memo(function UserMini({ pubkey }: { pubkey: string }) {
|
||||
return res.data;
|
||||
}, []);
|
||||
|
||||
const getCacheProfile = useCallback(async () => {
|
||||
const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`);
|
||||
return result[0];
|
||||
}, [db, pubkey]);
|
||||
|
||||
const insertCacheProfile = useCallback(
|
||||
async (event) => {
|
||||
// update state
|
||||
setProfile(JSON.parse(event.content));
|
||||
// insert to database
|
||||
await db.execute('INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES (?, ?);', [pubkey, event.content]);
|
||||
},
|
||||
[db, pubkey]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getCacheProfile()
|
||||
.then((res) => {
|
||||
if (res !== undefined) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res) => insertCacheProfile(res))
|
||||
.catch(console.error);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [fetchProfile, getCacheProfile, insertCacheProfile, pubkey]);
|
||||
getCacheProfile(pubkey).then((res) => {
|
||||
if (res) {
|
||||
setProfile(JSON.parse(res.metadata));
|
||||
} else {
|
||||
fetchProfile(pubkey)
|
||||
.then((res: any) => {
|
||||
setProfile(JSON.parse(res.content));
|
||||
createCacheProfile(pubkey, res.content);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
});
|
||||
}, [fetchProfile, pubkey]);
|
||||
|
||||
return (
|
||||
<div className="flex cursor-pointer items-center gap-2.5 rounded-md px-2.5 py-1.5 text-sm font-medium hover:bg-zinc-900">
|
||||
|
||||
Reference in New Issue
Block a user